1114402Sru// -*- C++ -*- 2151497Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005 3114402Sru Free Software Foundation, Inc. 4114402Sru Written by James Clark (jjc@jclark.com) 5114402Sru 6114402SruThis file is part of groff. 7114402Sru 8114402Srugroff is free software; you can redistribute it and/or modify it under 9114402Sruthe terms of the GNU General Public License as published by the Free 10114402SruSoftware Foundation; either version 2, or (at your option) any later 11114402Sruversion. 12114402Sru 13114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 14114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 15114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16114402Srufor more details. 17114402Sru 18114402SruYou should have received a copy of the GNU General Public License along 19114402Sruwith groff; see the file COPYING. If not, write to the Free Software 20151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 21114402Sru 22151497Sruextern int debug_state; 23151497Sru 24114402Sru#include "troff.h" 25114402Sru 26114402Sru#ifdef HAVE_UNISTD_H 27114402Sru#include <unistd.h> 28114402Sru#endif 29114402Sru 30114402Sru#include "dictionary.h" 31114402Sru#include "hvunits.h" 32151497Sru#include "stringclass.h" 33151497Sru#include "mtsm.h" 34114402Sru#include "env.h" 35114402Sru#include "request.h" 36114402Sru#include "node.h" 37114402Sru#include "token.h" 38151497Sru#include "div.h" 39151497Sru#include "reg.h" 40114402Sru#include "charinfo.h" 41114402Sru#include "font.h" 42114402Sru#include "input.h" 43114402Sru#include "geometry.h" 44114402Sru 45114402Sru#include "nonposix.h" 46114402Sru 47114402Sru#ifdef _POSIX_VERSION 48114402Sru 49114402Sru#include <sys/wait.h> 50114402Sru 51114402Sru#else /* not _POSIX_VERSION */ 52114402Sru 53114402Sru/* traditional Unix */ 54114402Sru 55114402Sru#define WIFEXITED(s) (((s) & 0377) == 0) 56114402Sru#define WEXITSTATUS(s) (((s) >> 8) & 0377) 57114402Sru#define WTERMSIG(s) ((s) & 0177) 58114402Sru#define WIFSTOPPED(s) (((s) & 0377) == 0177) 59114402Sru#define WSTOPSIG(s) (((s) >> 8) & 0377) 60114402Sru#define WIFSIGNALED(s) (((s) & 0377) != 0 && (((s) & 0377) != 0177)) 61114402Sru 62114402Sru#endif /* not _POSIX_VERSION */ 63114402Sru 64151497Sru// declarations to avoid friend name injections 65151497Sruclass tfont; 66151497Sruclass tfont_spec; 67151497Srutfont *make_tfont(tfont_spec &); 68151497Sru 69151497Sru 70114402Sru/* 71114402Sru * how many boundaries of images have been written? Useful for 72114402Sru * debugging grohtml 73114402Sru */ 74114402Sru 75114402Sruint image_no = 0; 76114402Srustatic int suppress_start_page = 0; 77114402Sru 78114402Sru#define STORE_WIDTH 1 79114402Sru 80114402Srusymbol HYPHEN_SYMBOL("hy"); 81114402Sru 82114402Sru// Character used when a hyphen is inserted at a line break. 83114402Srustatic charinfo *soft_hyphen_char; 84114402Sru 85114402Sruenum constant_space_type { 86114402Sru CONSTANT_SPACE_NONE, 87114402Sru CONSTANT_SPACE_RELATIVE, 88114402Sru CONSTANT_SPACE_ABSOLUTE 89114402Sru }; 90114402Sru 91114402Srustruct special_font_list { 92114402Sru int n; 93114402Sru special_font_list *next; 94114402Sru}; 95114402Sru 96114402Sruspecial_font_list *global_special_fonts; 97114402Srustatic int global_ligature_mode = 1; 98114402Srustatic int global_kern_mode = 1; 99114402Sru 100114402Sruclass track_kerning_function { 101114402Sru int non_zero; 102114402Sru units min_size; 103114402Sru hunits min_amount; 104114402Sru units max_size; 105114402Sru hunits max_amount; 106114402Srupublic: 107114402Sru track_kerning_function(); 108114402Sru track_kerning_function(units, hunits, units, hunits); 109114402Sru int operator==(const track_kerning_function &); 110114402Sru int operator!=(const track_kerning_function &); 111114402Sru hunits compute(int point_size); 112114402Sru}; 113114402Sru 114114402Sru// embolden fontno when this is the current font 115114402Sru 116114402Srustruct conditional_bold { 117114402Sru conditional_bold *next; 118114402Sru int fontno; 119114402Sru hunits offset; 120114402Sru conditional_bold(int, hunits, conditional_bold * = 0); 121114402Sru}; 122114402Sru 123114402Sruclass font_info { 124114402Sru tfont *last_tfont; 125114402Sru int number; 126114402Sru font_size last_size; 127114402Sru int last_height; 128114402Sru int last_slant; 129114402Sru symbol internal_name; 130114402Sru symbol external_name; 131114402Sru font *fm; 132114402Sru char is_bold; 133114402Sru hunits bold_offset; 134114402Sru track_kerning_function track_kern; 135114402Sru constant_space_type is_constant_spaced; 136114402Sru units constant_space; 137114402Sru int last_ligature_mode; 138114402Sru int last_kern_mode; 139114402Sru conditional_bold *cond_bold_list; 140114402Sru void flush(); 141114402Srupublic: 142114402Sru special_font_list *sf; 143151497Sru font_info(symbol, int, symbol, font *); 144114402Sru int contains(charinfo *); 145114402Sru void set_bold(hunits); 146114402Sru void unbold(); 147114402Sru void set_conditional_bold(int, hunits); 148114402Sru void conditional_unbold(int); 149114402Sru void set_track_kern(track_kerning_function &); 150114402Sru void set_constant_space(constant_space_type, units = 0); 151114402Sru int is_named(symbol); 152114402Sru symbol get_name(); 153114402Sru tfont *get_tfont(font_size, int, int, int); 154114402Sru hunits get_space_width(font_size, int); 155114402Sru hunits get_narrow_space_width(font_size); 156114402Sru hunits get_half_narrow_space_width(font_size); 157114402Sru int get_bold(hunits *); 158114402Sru int is_special(); 159114402Sru int is_style(); 160114402Sru friend symbol get_font_name(int, environment *); 161151497Sru friend symbol get_style_name(int); 162114402Sru}; 163114402Sru 164114402Sruclass tfont_spec { 165114402Sruprotected: 166114402Sru symbol name; 167114402Sru int input_position; 168114402Sru font *fm; 169114402Sru font_size size; 170114402Sru char is_bold; 171114402Sru char is_constant_spaced; 172114402Sru int ligature_mode; 173114402Sru int kern_mode; 174114402Sru hunits bold_offset; 175114402Sru hunits track_kern; // add this to the width 176114402Sru hunits constant_space_width; 177114402Sru int height; 178114402Sru int slant; 179114402Srupublic: 180151497Sru tfont_spec(symbol, int, font *, font_size, int, int); 181114402Sru tfont_spec(const tfont_spec &spec) { *this = spec; } 182114402Sru tfont_spec plain(); 183114402Sru int operator==(const tfont_spec &); 184114402Sru friend tfont *font_info::get_tfont(font_size fs, int, int, int); 185114402Sru}; 186114402Sru 187114402Sruclass tfont : public tfont_spec { 188114402Sru static tfont *tfont_list; 189114402Sru tfont *next; 190114402Sru tfont *plain_version; 191114402Srupublic: 192114402Sru tfont(tfont_spec &); 193114402Sru int contains(charinfo *); 194114402Sru hunits get_width(charinfo *c); 195114402Sru int get_bold(hunits *); 196114402Sru int get_constant_space(hunits *); 197114402Sru hunits get_track_kern(); 198114402Sru tfont *get_plain(); 199114402Sru font_size get_size(); 200114402Sru symbol get_name(); 201114402Sru charinfo *get_lig(charinfo *c1, charinfo *c2); 202114402Sru int get_kern(charinfo *c1, charinfo *c2, hunits *res); 203114402Sru int get_input_position(); 204114402Sru int get_character_type(charinfo *); 205114402Sru int get_height(); 206114402Sru int get_slant(); 207114402Sru vunits get_char_height(charinfo *); 208114402Sru vunits get_char_depth(charinfo *); 209114402Sru hunits get_char_skew(charinfo *); 210114402Sru hunits get_italic_correction(charinfo *); 211114402Sru hunits get_left_italic_correction(charinfo *); 212114402Sru hunits get_subscript_correction(charinfo *); 213114402Sru friend tfont *make_tfont(tfont_spec &); 214114402Sru}; 215114402Sru 216114402Sruinline int env_definite_font(environment *env) 217114402Sru{ 218114402Sru return env->get_family()->make_definite(env->get_font()); 219114402Sru} 220114402Sru 221114402Sru/* font_info functions */ 222114402Sru 223114402Srustatic font_info **font_table = 0; 224114402Srustatic int font_table_size = 0; 225114402Sru 226114402Srufont_info::font_info(symbol nm, int n, symbol enm, font *f) 227114402Sru: last_tfont(0), number(n), last_size(0), 228114402Sru internal_name(nm), external_name(enm), fm(f), 229114402Sru is_bold(0), is_constant_spaced(CONSTANT_SPACE_NONE), last_ligature_mode(1), 230114402Sru last_kern_mode(1), cond_bold_list(0), sf(0) 231114402Sru{ 232114402Sru} 233114402Sru 234114402Sruinline int font_info::contains(charinfo *ci) 235114402Sru{ 236114402Sru return fm != 0 && fm->contains(ci->get_index()); 237114402Sru} 238114402Sru 239114402Sruinline int font_info::is_special() 240114402Sru{ 241114402Sru return fm != 0 && fm->is_special(); 242114402Sru} 243114402Sru 244114402Sruinline int font_info::is_style() 245114402Sru{ 246114402Sru return fm == 0; 247114402Sru} 248114402Sru 249114402Srutfont *make_tfont(tfont_spec &spec) 250114402Sru{ 251114402Sru for (tfont *p = tfont::tfont_list; p; p = p->next) 252114402Sru if (*p == spec) 253114402Sru return p; 254114402Sru return new tfont(spec); 255114402Sru} 256114402Sru 257114402Sru// this is the current_font, fontno is where we found the character, 258114402Sru// presumably a special font 259114402Sru 260114402Srutfont *font_info::get_tfont(font_size fs, int height, int slant, int fontno) 261114402Sru{ 262114402Sru if (last_tfont == 0 || fs != last_size 263114402Sru || height != last_height || slant != last_slant 264114402Sru || global_ligature_mode != last_ligature_mode 265114402Sru || global_kern_mode != last_kern_mode 266114402Sru || fontno != number) { 267114402Sru font_info *f = font_table[fontno]; 268114402Sru tfont_spec spec(f->external_name, f->number, f->fm, fs, height, slant); 269114402Sru for (conditional_bold *p = cond_bold_list; p; p = p->next) 270114402Sru if (p->fontno == fontno) { 271114402Sru spec.is_bold = 1; 272114402Sru spec.bold_offset = p->offset; 273114402Sru break; 274114402Sru } 275114402Sru if (!spec.is_bold && is_bold) { 276114402Sru spec.is_bold = 1; 277114402Sru spec.bold_offset = bold_offset; 278114402Sru } 279114402Sru spec.track_kern = track_kern.compute(fs.to_scaled_points()); 280114402Sru spec.ligature_mode = global_ligature_mode; 281114402Sru spec.kern_mode = global_kern_mode; 282114402Sru switch (is_constant_spaced) { 283114402Sru case CONSTANT_SPACE_NONE: 284114402Sru break; 285114402Sru case CONSTANT_SPACE_ABSOLUTE: 286114402Sru spec.is_constant_spaced = 1; 287114402Sru spec.constant_space_width = constant_space; 288114402Sru break; 289114402Sru case CONSTANT_SPACE_RELATIVE: 290114402Sru spec.is_constant_spaced = 1; 291114402Sru spec.constant_space_width 292114402Sru = scale(constant_space*fs.to_scaled_points(), 293114402Sru units_per_inch, 294114402Sru 36*72*sizescale); 295114402Sru break; 296114402Sru default: 297114402Sru assert(0); 298114402Sru } 299114402Sru if (fontno != number) 300114402Sru return make_tfont(spec); 301114402Sru last_tfont = make_tfont(spec); 302114402Sru last_size = fs; 303114402Sru last_height = height; 304114402Sru last_slant = slant; 305114402Sru last_ligature_mode = global_ligature_mode; 306114402Sru last_kern_mode = global_kern_mode; 307114402Sru } 308114402Sru return last_tfont; 309114402Sru} 310114402Sru 311114402Sruint font_info::get_bold(hunits *res) 312114402Sru{ 313114402Sru if (is_bold) { 314114402Sru *res = bold_offset; 315114402Sru return 1; 316114402Sru } 317114402Sru else 318114402Sru return 0; 319114402Sru} 320114402Sru 321114402Sruvoid font_info::unbold() 322114402Sru{ 323114402Sru if (is_bold) { 324114402Sru is_bold = 0; 325114402Sru flush(); 326114402Sru } 327114402Sru} 328114402Sru 329114402Sruvoid font_info::set_bold(hunits offset) 330114402Sru{ 331114402Sru if (!is_bold || offset != bold_offset) { 332114402Sru is_bold = 1; 333114402Sru bold_offset = offset; 334114402Sru flush(); 335114402Sru } 336114402Sru} 337114402Sru 338114402Sruvoid font_info::set_conditional_bold(int fontno, hunits offset) 339114402Sru{ 340114402Sru for (conditional_bold *p = cond_bold_list; p; p = p->next) 341114402Sru if (p->fontno == fontno) { 342114402Sru if (offset != p->offset) { 343114402Sru p->offset = offset; 344114402Sru flush(); 345114402Sru } 346114402Sru return; 347114402Sru } 348114402Sru cond_bold_list = new conditional_bold(fontno, offset, cond_bold_list); 349114402Sru} 350114402Sru 351114402Sruconditional_bold::conditional_bold(int f, hunits h, conditional_bold *x) 352114402Sru: next(x), fontno(f), offset(h) 353114402Sru{ 354114402Sru} 355114402Sru 356114402Sruvoid font_info::conditional_unbold(int fontno) 357114402Sru{ 358114402Sru for (conditional_bold **p = &cond_bold_list; *p; p = &(*p)->next) 359114402Sru if ((*p)->fontno == fontno) { 360114402Sru conditional_bold *tem = *p; 361114402Sru *p = (*p)->next; 362114402Sru delete tem; 363114402Sru flush(); 364114402Sru return; 365114402Sru } 366114402Sru} 367114402Sru 368114402Sruvoid font_info::set_constant_space(constant_space_type type, units x) 369114402Sru{ 370114402Sru if (type != is_constant_spaced 371114402Sru || (type != CONSTANT_SPACE_NONE && x != constant_space)) { 372114402Sru flush(); 373114402Sru is_constant_spaced = type; 374114402Sru constant_space = x; 375114402Sru } 376114402Sru} 377114402Sru 378114402Sruvoid font_info::set_track_kern(track_kerning_function &tk) 379114402Sru{ 380114402Sru if (track_kern != tk) { 381114402Sru track_kern = tk; 382114402Sru flush(); 383114402Sru } 384114402Sru} 385114402Sru 386114402Sruvoid font_info::flush() 387114402Sru{ 388114402Sru last_tfont = 0; 389114402Sru} 390114402Sru 391114402Sruint font_info::is_named(symbol s) 392114402Sru{ 393114402Sru return internal_name == s; 394114402Sru} 395114402Sru 396114402Srusymbol font_info::get_name() 397114402Sru{ 398114402Sru return internal_name; 399114402Sru} 400114402Sru 401114402Srusymbol get_font_name(int fontno, environment *env) 402114402Sru{ 403114402Sru symbol f = font_table[fontno]->get_name(); 404114402Sru if (font_table[fontno]->is_style()) { 405114402Sru return concat(env->get_family()->nm, f); 406114402Sru } 407114402Sru return f; 408114402Sru} 409114402Sru 410151497Srusymbol get_style_name(int fontno) 411114402Sru{ 412151497Sru if (font_table[fontno]->is_style()) 413151497Sru return font_table[fontno]->get_name(); 414151497Sru else 415151497Sru return EMPTY_SYMBOL; 416151497Sru} 417151497Sru 418151497Sruhunits font_info::get_space_width(font_size fs, int space_sz) 419151497Sru{ 420114402Sru if (is_constant_spaced == CONSTANT_SPACE_NONE) 421114402Sru return scale(hunits(fm->get_space_width(fs.to_scaled_points())), 422151497Sru space_sz, 12); 423114402Sru else if (is_constant_spaced == CONSTANT_SPACE_ABSOLUTE) 424114402Sru return constant_space; 425114402Sru else 426114402Sru return scale(constant_space*fs.to_scaled_points(), 427114402Sru units_per_inch, 36*72*sizescale); 428114402Sru} 429114402Sru 430114402Sruhunits font_info::get_narrow_space_width(font_size fs) 431114402Sru{ 432114402Sru charinfo *ci = get_charinfo(symbol("|")); 433114402Sru if (fm->contains(ci->get_index())) 434114402Sru return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points())); 435114402Sru else 436114402Sru return hunits(fs.to_units()/6); 437114402Sru} 438114402Sru 439114402Sruhunits font_info::get_half_narrow_space_width(font_size fs) 440114402Sru{ 441114402Sru charinfo *ci = get_charinfo(symbol("^")); 442114402Sru if (fm->contains(ci->get_index())) 443114402Sru return hunits(fm->get_width(ci->get_index(), fs.to_scaled_points())); 444114402Sru else 445114402Sru return hunits(fs.to_units()/12); 446114402Sru} 447114402Sru 448114402Sru/* tfont */ 449114402Sru 450114402Srutfont_spec::tfont_spec(symbol nm, int n, font *f, 451114402Sru font_size s, int h, int sl) 452114402Sru: name(nm), input_position(n), fm(f), size(s), 453114402Sru is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1), 454114402Sru height(h), slant(sl) 455114402Sru{ 456114402Sru if (height == size.to_scaled_points()) 457114402Sru height = 0; 458114402Sru} 459114402Sru 460114402Sruint tfont_spec::operator==(const tfont_spec &spec) 461114402Sru{ 462114402Sru if (fm == spec.fm 463114402Sru && size == spec.size 464114402Sru && input_position == spec.input_position 465114402Sru && name == spec.name 466114402Sru && height == spec.height 467114402Sru && slant == spec.slant 468114402Sru && (is_bold 469114402Sru ? (spec.is_bold && bold_offset == spec.bold_offset) 470114402Sru : !spec.is_bold) 471114402Sru && track_kern == spec.track_kern 472114402Sru && (is_constant_spaced 473114402Sru ? (spec.is_constant_spaced 474114402Sru && constant_space_width == spec.constant_space_width) 475114402Sru : !spec.is_constant_spaced) 476114402Sru && ligature_mode == spec.ligature_mode 477114402Sru && kern_mode == spec.kern_mode) 478114402Sru return 1; 479114402Sru else 480114402Sru return 0; 481114402Sru} 482114402Sru 483114402Srutfont_spec tfont_spec::plain() 484114402Sru{ 485114402Sru return tfont_spec(name, input_position, fm, size, height, slant); 486114402Sru} 487114402Sru 488114402Sruhunits tfont::get_width(charinfo *c) 489114402Sru{ 490114402Sru if (is_constant_spaced) 491114402Sru return constant_space_width; 492114402Sru else if (is_bold) 493114402Sru return (hunits(fm->get_width(c->get_index(), size.to_scaled_points())) 494114402Sru + track_kern + bold_offset); 495114402Sru else 496114402Sru return (hunits(fm->get_width(c->get_index(), size.to_scaled_points())) 497114402Sru + track_kern); 498114402Sru} 499114402Sru 500114402Sruvunits tfont::get_char_height(charinfo *c) 501114402Sru{ 502114402Sru vunits v = fm->get_height(c->get_index(), size.to_scaled_points()); 503114402Sru if (height != 0 && height != size.to_scaled_points()) 504114402Sru return scale(v, height, size.to_scaled_points()); 505114402Sru else 506114402Sru return v; 507114402Sru} 508114402Sru 509114402Sruvunits tfont::get_char_depth(charinfo *c) 510114402Sru{ 511114402Sru vunits v = fm->get_depth(c->get_index(), size.to_scaled_points()); 512114402Sru if (height != 0 && height != size.to_scaled_points()) 513114402Sru return scale(v, height, size.to_scaled_points()); 514114402Sru else 515114402Sru return v; 516114402Sru} 517114402Sru 518114402Sruhunits tfont::get_char_skew(charinfo *c) 519114402Sru{ 520114402Sru return hunits(fm->get_skew(c->get_index(), size.to_scaled_points(), slant)); 521114402Sru} 522114402Sru 523114402Sruhunits tfont::get_italic_correction(charinfo *c) 524114402Sru{ 525114402Sru return hunits(fm->get_italic_correction(c->get_index(), size.to_scaled_points())); 526114402Sru} 527114402Sru 528114402Sruhunits tfont::get_left_italic_correction(charinfo *c) 529114402Sru{ 530114402Sru return hunits(fm->get_left_italic_correction(c->get_index(), 531114402Sru size.to_scaled_points())); 532114402Sru} 533114402Sru 534114402Sruhunits tfont::get_subscript_correction(charinfo *c) 535114402Sru{ 536114402Sru return hunits(fm->get_subscript_correction(c->get_index(), 537114402Sru size.to_scaled_points())); 538114402Sru} 539114402Sru 540114402Sruinline int tfont::get_input_position() 541114402Sru{ 542114402Sru return input_position; 543114402Sru} 544114402Sru 545114402Sruinline int tfont::contains(charinfo *ci) 546114402Sru{ 547114402Sru return fm->contains(ci->get_index()); 548114402Sru} 549114402Sru 550114402Sruinline int tfont::get_character_type(charinfo *ci) 551114402Sru{ 552114402Sru return fm->get_character_type(ci->get_index()); 553114402Sru} 554114402Sru 555114402Sruinline int tfont::get_bold(hunits *res) 556114402Sru{ 557114402Sru if (is_bold) { 558114402Sru *res = bold_offset; 559114402Sru return 1; 560114402Sru } 561114402Sru else 562114402Sru return 0; 563114402Sru} 564114402Sru 565114402Sruinline int tfont::get_constant_space(hunits *res) 566114402Sru{ 567114402Sru if (is_constant_spaced) { 568114402Sru *res = constant_space_width; 569114402Sru return 1; 570114402Sru } 571114402Sru else 572114402Sru return 0; 573114402Sru} 574114402Sru 575114402Sruinline hunits tfont::get_track_kern() 576114402Sru{ 577114402Sru return track_kern; 578114402Sru} 579114402Sru 580114402Sruinline tfont *tfont::get_plain() 581114402Sru{ 582114402Sru return plain_version; 583114402Sru} 584114402Sru 585114402Sruinline font_size tfont::get_size() 586114402Sru{ 587114402Sru return size; 588114402Sru} 589114402Sru 590114402Sruinline symbol tfont::get_name() 591114402Sru{ 592114402Sru return name; 593114402Sru} 594114402Sru 595114402Sruinline int tfont::get_height() 596114402Sru{ 597114402Sru return height; 598114402Sru} 599114402Sru 600114402Sruinline int tfont::get_slant() 601114402Sru{ 602114402Sru return slant; 603114402Sru} 604114402Sru 605114402Srusymbol SYMBOL_ff("ff"); 606114402Srusymbol SYMBOL_fi("fi"); 607114402Srusymbol SYMBOL_fl("fl"); 608114402Srusymbol SYMBOL_Fi("Fi"); 609114402Srusymbol SYMBOL_Fl("Fl"); 610114402Sru 611114402Srucharinfo *tfont::get_lig(charinfo *c1, charinfo *c2) 612114402Sru{ 613114402Sru if (ligature_mode == 0) 614114402Sru return 0; 615114402Sru charinfo *ci = 0; 616114402Sru if (c1->get_ascii_code() == 'f') { 617114402Sru switch (c2->get_ascii_code()) { 618114402Sru case 'f': 619114402Sru if (fm->has_ligature(font::LIG_ff)) 620114402Sru ci = get_charinfo(SYMBOL_ff); 621114402Sru break; 622114402Sru case 'i': 623114402Sru if (fm->has_ligature(font::LIG_fi)) 624114402Sru ci = get_charinfo(SYMBOL_fi); 625114402Sru break; 626114402Sru case 'l': 627114402Sru if (fm->has_ligature(font::LIG_fl)) 628114402Sru ci = get_charinfo(SYMBOL_fl); 629114402Sru break; 630114402Sru } 631114402Sru } 632114402Sru else if (ligature_mode != 2 && c1->nm == SYMBOL_ff) { 633114402Sru switch (c2->get_ascii_code()) { 634114402Sru case 'i': 635114402Sru if (fm->has_ligature(font::LIG_ffi)) 636114402Sru ci = get_charinfo(SYMBOL_Fi); 637114402Sru break; 638114402Sru case 'l': 639114402Sru if (fm->has_ligature(font::LIG_ffl)) 640114402Sru ci = get_charinfo(SYMBOL_Fl); 641114402Sru break; 642114402Sru } 643114402Sru } 644114402Sru if (ci != 0 && fm->contains(ci->get_index())) 645114402Sru return ci; 646114402Sru return 0; 647114402Sru} 648114402Sru 649114402Sruinline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res) 650114402Sru{ 651114402Sru if (kern_mode == 0) 652114402Sru return 0; 653114402Sru else { 654114402Sru int n = fm->get_kern(c1->get_index(), 655114402Sru c2->get_index(), 656114402Sru size.to_scaled_points()); 657114402Sru if (n) { 658114402Sru *res = hunits(n); 659114402Sru return 1; 660114402Sru } 661114402Sru else 662114402Sru return 0; 663114402Sru } 664114402Sru} 665114402Sru 666114402Srutfont *tfont::tfont_list = 0; 667114402Sru 668114402Srutfont::tfont(tfont_spec &spec) : tfont_spec(spec) 669114402Sru{ 670114402Sru next = tfont_list; 671114402Sru tfont_list = this; 672114402Sru tfont_spec plain_spec = plain(); 673114402Sru tfont *p; 674114402Sru for (p = tfont_list; p; p = p->next) 675114402Sru if (*p == plain_spec) { 676114402Sru plain_version = p; 677114402Sru break; 678114402Sru } 679114402Sru if (!p) 680114402Sru plain_version = new tfont(plain_spec); 681114402Sru} 682114402Sru 683114402Sru/* output_file */ 684114402Sru 685114402Sruclass real_output_file : public output_file { 686114402Sru#ifndef POPEN_MISSING 687114402Sru int piped; 688114402Sru#endif 689114402Sru int printing; // decision via optional page list 690114402Sru int output_on; // \O[0] or \O[1] escape calls 691114402Sru virtual void really_transparent_char(unsigned char) = 0; 692114402Sru virtual void really_print_line(hunits x, vunits y, node *n, 693114402Sru vunits before, vunits after, hunits width) = 0; 694114402Sru virtual void really_begin_page(int pageno, vunits page_length) = 0; 695114402Sru virtual void really_copy_file(hunits x, vunits y, const char *filename); 696114402Sru virtual void really_put_filename(const char *filename); 697114402Sru virtual void really_on(); 698114402Sru virtual void really_off(); 699151497Srupublic: 700114402Sru FILE *fp; 701114402Sru real_output_file(); 702114402Sru ~real_output_file(); 703114402Sru void flush(); 704114402Sru void transparent_char(unsigned char); 705114402Sru void print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width); 706114402Sru void begin_page(int pageno, vunits page_length); 707114402Sru void put_filename(const char *filename); 708114402Sru void on(); 709114402Sru void off(); 710114402Sru int is_on(); 711114402Sru int is_printing(); 712114402Sru void copy_file(hunits x, vunits y, const char *filename); 713114402Sru}; 714114402Sru 715114402Sruclass suppress_output_file : public real_output_file { 716114402Srupublic: 717114402Sru suppress_output_file(); 718114402Sru void really_transparent_char(unsigned char); 719114402Sru void really_print_line(hunits x, vunits y, node *n, vunits, vunits, hunits width); 720114402Sru void really_begin_page(int pageno, vunits page_length); 721114402Sru}; 722114402Sru 723114402Sruclass ascii_output_file : public real_output_file { 724114402Srupublic: 725114402Sru ascii_output_file(); 726114402Sru void really_transparent_char(unsigned char); 727114402Sru void really_print_line(hunits x, vunits y, node *n, vunits, vunits, hunits width); 728114402Sru void really_begin_page(int pageno, vunits page_length); 729114402Sru void outc(unsigned char c); 730114402Sru void outs(const char *s); 731114402Sru}; 732114402Sru 733114402Sruvoid ascii_output_file::outc(unsigned char c) 734114402Sru{ 735114402Sru fputc(c, fp); 736114402Sru} 737114402Sru 738114402Sruvoid ascii_output_file::outs(const char *s) 739114402Sru{ 740114402Sru fputc('<', fp); 741114402Sru if (s) 742114402Sru fputs(s, fp); 743114402Sru fputc('>', fp); 744114402Sru} 745114402Sru 746114402Srustruct hvpair; 747114402Sru 748114402Sruclass troff_output_file : public real_output_file { 749114402Sru units hpos; 750114402Sru units vpos; 751114402Sru units output_vpos; 752114402Sru units output_hpos; 753114402Sru int force_motion; 754114402Sru int current_size; 755114402Sru int current_slant; 756114402Sru int current_height; 757114402Sru tfont *current_tfont; 758114402Sru color *current_fill_color; 759114402Sru color *current_glyph_color; 760114402Sru int current_font_number; 761114402Sru symbol *font_position; 762114402Sru int nfont_positions; 763114402Sru enum { TBUF_SIZE = 256 }; 764114402Sru char tbuf[TBUF_SIZE]; 765114402Sru int tbuf_len; 766114402Sru int tbuf_kern; 767114402Sru int begun_page; 768151497Sru int cur_div_level; 769151497Sru string tag_list; 770114402Sru void do_motion(); 771114402Sru void put(char c); 772114402Sru void put(unsigned char c); 773114402Sru void put(int i); 774114402Sru void put(unsigned int i); 775114402Sru void put(const char *s); 776114402Sru void set_font(tfont *tf); 777114402Sru void flush_tbuf(); 778114402Srupublic: 779114402Sru troff_output_file(); 780114402Sru ~troff_output_file(); 781114402Sru void trailer(vunits page_length); 782114402Sru void put_char(charinfo *, tfont *, color *, color *); 783114402Sru void put_char_width(charinfo *, tfont *, color *, color *, hunits, hunits); 784114402Sru void right(hunits); 785114402Sru void down(vunits); 786114402Sru void moveto(hunits, vunits); 787114402Sru void start_special(tfont *, color *, color *, int = 0); 788114402Sru void start_special(); 789114402Sru void special_char(unsigned char c); 790114402Sru void end_special(); 791114402Sru void word_marker(); 792114402Sru void really_transparent_char(unsigned char c); 793114402Sru void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width); 794114402Sru void really_begin_page(int pageno, vunits page_length); 795114402Sru void really_copy_file(hunits x, vunits y, const char *filename); 796114402Sru void really_put_filename(const char *filename); 797114402Sru void really_on(); 798114402Sru void really_off(); 799114402Sru void draw(char, hvpair *, int, font_size, color *, color *); 800114402Sru void determine_line_limits (char code, hvpair *point, int npoints); 801114402Sru void check_charinfo(tfont *tf, charinfo *ci); 802114402Sru void glyph_color(color *c); 803114402Sru void fill_color(color *c); 804114402Sru int get_hpos() { return hpos; } 805114402Sru int get_vpos() { return vpos; } 806151497Sru void add_to_tag_list(string s); 807114402Sru friend void space_char_hmotion_node::tprint(troff_output_file *); 808114402Sru friend void unbreakable_space_node::tprint(troff_output_file *); 809114402Sru}; 810114402Sru 811114402Srustatic void put_string(const char *s, FILE *fp) 812114402Sru{ 813114402Sru for (; *s != '\0'; ++s) 814114402Sru putc(*s, fp); 815114402Sru} 816114402Sru 817114402Sruinline void troff_output_file::put(char c) 818114402Sru{ 819114402Sru putc(c, fp); 820114402Sru} 821114402Sru 822114402Sruinline void troff_output_file::put(unsigned char c) 823114402Sru{ 824114402Sru putc(c, fp); 825114402Sru} 826114402Sru 827114402Sruinline void troff_output_file::put(const char *s) 828114402Sru{ 829114402Sru put_string(s, fp); 830114402Sru} 831114402Sru 832114402Sruinline void troff_output_file::put(int i) 833114402Sru{ 834114402Sru put_string(i_to_a(i), fp); 835114402Sru} 836114402Sru 837114402Sruinline void troff_output_file::put(unsigned int i) 838114402Sru{ 839114402Sru put_string(ui_to_a(i), fp); 840114402Sru} 841114402Sru 842114402Sruvoid troff_output_file::start_special(tfont *tf, color *gcol, color *fcol, 843114402Sru int no_init_string) 844114402Sru{ 845114402Sru set_font(tf); 846114402Sru glyph_color(gcol); 847114402Sru fill_color(fcol); 848114402Sru flush_tbuf(); 849114402Sru do_motion(); 850114402Sru if (!no_init_string) 851114402Sru put("x X "); 852114402Sru} 853114402Sru 854114402Sruvoid troff_output_file::start_special() 855114402Sru{ 856114402Sru flush_tbuf(); 857114402Sru do_motion(); 858114402Sru put("x X "); 859114402Sru} 860114402Sru 861114402Sruvoid troff_output_file::special_char(unsigned char c) 862114402Sru{ 863114402Sru put(c); 864114402Sru if (c == '\n') 865114402Sru put('+'); 866114402Sru} 867114402Sru 868114402Sruvoid troff_output_file::end_special() 869114402Sru{ 870114402Sru put('\n'); 871114402Sru} 872114402Sru 873114402Sruinline void troff_output_file::moveto(hunits h, vunits v) 874114402Sru{ 875114402Sru hpos = h.to_units(); 876114402Sru vpos = v.to_units(); 877114402Sru} 878114402Sru 879114402Sruvoid troff_output_file::really_print_line(hunits x, vunits y, node *n, 880114402Sru vunits before, vunits after, hunits) 881114402Sru{ 882114402Sru moveto(x, y); 883114402Sru while (n != 0) { 884151497Sru // Check whether we should push the current troff state and use 885151497Sru // the state at the start of the invocation of this diversion. 886151497Sru if (n->div_nest_level > cur_div_level && n->push_state) { 887151497Sru state.push_state(n->push_state); 888151497Sru cur_div_level = n->div_nest_level; 889151497Sru } 890151497Sru // Has the current diversion level decreased? Then we must pop the 891151497Sru // troff state. 892151497Sru while (n->div_nest_level < cur_div_level) { 893151497Sru state.pop_state(); 894151497Sru cur_div_level = n->div_nest_level; 895151497Sru } 896151497Sru // Now check whether the state has changed. 897151497Sru if ((is_on() || n->force_tprint()) 898151497Sru && (state.changed(n->state) || n->is_tag() || n->is_special)) { 899151497Sru flush_tbuf(); 900151497Sru do_motion(); 901151497Sru force_motion = 1; 902151497Sru flush(); 903151497Sru state.flush(fp, n->state, tag_list); 904151497Sru tag_list = string(""); 905151497Sru flush(); 906151497Sru } 907114402Sru n->tprint(this); 908114402Sru n = n->next; 909114402Sru } 910114402Sru flush_tbuf(); 911114402Sru // This ensures that transparent throughput will have a more predictable 912114402Sru // position. 913114402Sru do_motion(); 914114402Sru force_motion = 1; 915114402Sru hpos = 0; 916114402Sru put('n'); 917114402Sru put(before.to_units()); 918114402Sru put(' '); 919114402Sru put(after.to_units()); 920114402Sru put('\n'); 921114402Sru} 922114402Sru 923114402Sruinline void troff_output_file::word_marker() 924114402Sru{ 925114402Sru flush_tbuf(); 926114402Sru if (is_on()) 927114402Sru put('w'); 928114402Sru} 929114402Sru 930114402Sruinline void troff_output_file::right(hunits n) 931114402Sru{ 932114402Sru hpos += n.to_units(); 933114402Sru} 934114402Sru 935114402Sruinline void troff_output_file::down(vunits n) 936114402Sru{ 937114402Sru vpos += n.to_units(); 938114402Sru} 939114402Sru 940114402Sruvoid troff_output_file::do_motion() 941114402Sru{ 942114402Sru if (force_motion) { 943114402Sru put('V'); 944114402Sru put(vpos); 945114402Sru put('\n'); 946114402Sru put('H'); 947114402Sru put(hpos); 948114402Sru put('\n'); 949114402Sru } 950114402Sru else { 951114402Sru if (hpos != output_hpos) { 952114402Sru units n = hpos - output_hpos; 953114402Sru if (n > 0 && n < hpos) { 954114402Sru put('h'); 955114402Sru put(n); 956114402Sru } 957114402Sru else { 958114402Sru put('H'); 959114402Sru put(hpos); 960114402Sru } 961114402Sru put('\n'); 962114402Sru } 963114402Sru if (vpos != output_vpos) { 964114402Sru units n = vpos - output_vpos; 965114402Sru if (n > 0 && n < vpos) { 966114402Sru put('v'); 967114402Sru put(n); 968114402Sru } 969114402Sru else { 970114402Sru put('V'); 971114402Sru put(vpos); 972114402Sru } 973114402Sru put('\n'); 974114402Sru } 975114402Sru } 976114402Sru output_vpos = vpos; 977114402Sru output_hpos = hpos; 978114402Sru force_motion = 0; 979114402Sru} 980114402Sru 981114402Sruvoid troff_output_file::flush_tbuf() 982114402Sru{ 983114402Sru if (!is_on()) { 984114402Sru tbuf_len = 0; 985114402Sru return; 986114402Sru } 987114402Sru 988114402Sru if (tbuf_len == 0) 989114402Sru return; 990114402Sru if (tbuf_kern == 0) 991114402Sru put('t'); 992114402Sru else { 993114402Sru put('u'); 994114402Sru put(tbuf_kern); 995114402Sru put(' '); 996114402Sru } 997114402Sru check_output_limits(hpos, vpos); 998114402Sru check_output_limits(hpos, vpos - current_size); 999114402Sru 1000114402Sru for (int i = 0; i < tbuf_len; i++) 1001114402Sru put(tbuf[i]); 1002114402Sru put('\n'); 1003114402Sru tbuf_len = 0; 1004114402Sru} 1005114402Sru 1006114402Sruvoid troff_output_file::check_charinfo(tfont *tf, charinfo *ci) 1007114402Sru{ 1008114402Sru if (!is_on()) 1009114402Sru return; 1010114402Sru 1011114402Sru int height = tf->get_char_height(ci).to_units(); 1012114402Sru int width = tf->get_width(ci).to_units() 1013114402Sru + tf->get_italic_correction(ci).to_units(); 1014114402Sru int depth = tf->get_char_depth(ci).to_units(); 1015114402Sru check_output_limits(output_hpos, output_vpos - height); 1016114402Sru check_output_limits(output_hpos + width, output_vpos + depth); 1017114402Sru} 1018114402Sru 1019114402Sruvoid troff_output_file::put_char_width(charinfo *ci, tfont *tf, 1020114402Sru color *gcol, color *fcol, 1021114402Sru hunits w, hunits k) 1022114402Sru{ 1023114402Sru int kk = k.to_units(); 1024114402Sru if (!is_on()) { 1025114402Sru flush_tbuf(); 1026114402Sru hpos += w.to_units() + kk; 1027114402Sru return; 1028114402Sru } 1029114402Sru set_font(tf); 1030151497Sru unsigned char c = ci->get_ascii_code(); 1031114402Sru if (c == '\0') { 1032114402Sru glyph_color(gcol); 1033114402Sru fill_color(fcol); 1034114402Sru flush_tbuf(); 1035114402Sru do_motion(); 1036114402Sru check_charinfo(tf, ci); 1037114402Sru if (ci->numbered()) { 1038114402Sru put('N'); 1039114402Sru put(ci->get_number()); 1040114402Sru } 1041114402Sru else { 1042114402Sru put('C'); 1043114402Sru const char *s = ci->nm.contents(); 1044114402Sru if (s[1] == 0) { 1045114402Sru put('\\'); 1046114402Sru put(s[0]); 1047114402Sru } 1048114402Sru else 1049114402Sru put(s); 1050114402Sru } 1051114402Sru put('\n'); 1052114402Sru hpos += w.to_units() + kk; 1053114402Sru } 1054114402Sru else if (tcommand_flag) { 1055114402Sru if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos 1056114402Sru && (!gcol || gcol == current_glyph_color) 1057114402Sru && (!fcol || fcol == current_fill_color) 1058114402Sru && kk == tbuf_kern 1059114402Sru && tbuf_len < TBUF_SIZE) { 1060114402Sru check_charinfo(tf, ci); 1061114402Sru tbuf[tbuf_len++] = c; 1062114402Sru output_hpos += w.to_units() + kk; 1063114402Sru hpos = output_hpos; 1064114402Sru return; 1065114402Sru } 1066114402Sru glyph_color(gcol); 1067114402Sru fill_color(fcol); 1068114402Sru flush_tbuf(); 1069114402Sru do_motion(); 1070114402Sru check_charinfo(tf, ci); 1071114402Sru tbuf[tbuf_len++] = c; 1072114402Sru output_hpos += w.to_units() + kk; 1073114402Sru tbuf_kern = kk; 1074114402Sru hpos = output_hpos; 1075114402Sru } 1076114402Sru else { 1077114402Sru // flush_tbuf(); 1078114402Sru int n = hpos - output_hpos; 1079114402Sru check_charinfo(tf, ci); 1080114402Sru // check_output_limits(output_hpos, output_vpos); 1081114402Sru if (vpos == output_vpos 1082114402Sru && (!gcol || gcol == current_glyph_color) 1083114402Sru && (!fcol || fcol == current_fill_color) 1084114402Sru && n > 0 && n < 100 && !force_motion) { 1085114402Sru put(char(n/10 + '0')); 1086114402Sru put(char(n%10 + '0')); 1087114402Sru put(c); 1088114402Sru output_hpos = hpos; 1089114402Sru } 1090114402Sru else { 1091114402Sru glyph_color(gcol); 1092114402Sru fill_color(fcol); 1093114402Sru do_motion(); 1094114402Sru put('c'); 1095114402Sru put(c); 1096114402Sru } 1097114402Sru hpos += w.to_units() + kk; 1098114402Sru } 1099114402Sru} 1100114402Sru 1101114402Sruvoid troff_output_file::put_char(charinfo *ci, tfont *tf, 1102114402Sru color *gcol, color *fcol) 1103114402Sru{ 1104114402Sru flush_tbuf(); 1105114402Sru if (!is_on()) 1106114402Sru return; 1107114402Sru set_font(tf); 1108151497Sru unsigned char c = ci->get_ascii_code(); 1109114402Sru if (c == '\0') { 1110114402Sru glyph_color(gcol); 1111114402Sru fill_color(fcol); 1112114402Sru flush_tbuf(); 1113114402Sru do_motion(); 1114114402Sru if (ci->numbered()) { 1115114402Sru put('N'); 1116114402Sru put(ci->get_number()); 1117114402Sru } 1118114402Sru else { 1119114402Sru put('C'); 1120114402Sru const char *s = ci->nm.contents(); 1121114402Sru if (s[1] == 0) { 1122114402Sru put('\\'); 1123114402Sru put(s[0]); 1124114402Sru } 1125114402Sru else 1126114402Sru put(s); 1127114402Sru } 1128114402Sru put('\n'); 1129114402Sru } 1130114402Sru else { 1131114402Sru int n = hpos - output_hpos; 1132114402Sru if (vpos == output_vpos 1133114402Sru && (!gcol || gcol == current_glyph_color) 1134114402Sru && (!fcol || fcol == current_fill_color) 1135114402Sru && n > 0 && n < 100) { 1136114402Sru put(char(n/10 + '0')); 1137114402Sru put(char(n%10 + '0')); 1138114402Sru put(c); 1139114402Sru output_hpos = hpos; 1140114402Sru } 1141114402Sru else { 1142114402Sru glyph_color(gcol); 1143114402Sru fill_color(fcol); 1144114402Sru flush_tbuf(); 1145114402Sru do_motion(); 1146114402Sru put('c'); 1147114402Sru put(c); 1148114402Sru } 1149114402Sru } 1150114402Sru} 1151114402Sru 1152114402Sru// set_font calls `flush_tbuf' if necessary. 1153114402Sru 1154114402Sruvoid troff_output_file::set_font(tfont *tf) 1155114402Sru{ 1156114402Sru if (current_tfont == tf) 1157114402Sru return; 1158114402Sru flush_tbuf(); 1159114402Sru int n = tf->get_input_position(); 1160114402Sru symbol nm = tf->get_name(); 1161114402Sru if (n >= nfont_positions || font_position[n] != nm) { 1162114402Sru put("x font "); 1163114402Sru put(n); 1164114402Sru put(' '); 1165114402Sru put(nm.contents()); 1166114402Sru put('\n'); 1167114402Sru if (n >= nfont_positions) { 1168114402Sru int old_nfont_positions = nfont_positions; 1169114402Sru symbol *old_font_position = font_position; 1170114402Sru nfont_positions *= 3; 1171114402Sru nfont_positions /= 2; 1172114402Sru if (nfont_positions <= n) 1173114402Sru nfont_positions = n + 10; 1174114402Sru font_position = new symbol[nfont_positions]; 1175114402Sru memcpy(font_position, old_font_position, 1176114402Sru old_nfont_positions*sizeof(symbol)); 1177114402Sru a_delete old_font_position; 1178114402Sru } 1179114402Sru font_position[n] = nm; 1180114402Sru } 1181114402Sru if (current_font_number != n) { 1182114402Sru put('f'); 1183114402Sru put(n); 1184114402Sru put('\n'); 1185114402Sru current_font_number = n; 1186114402Sru } 1187114402Sru int size = tf->get_size().to_scaled_points(); 1188114402Sru if (current_size != size) { 1189114402Sru put('s'); 1190114402Sru put(size); 1191114402Sru put('\n'); 1192114402Sru current_size = size; 1193114402Sru } 1194114402Sru int slant = tf->get_slant(); 1195114402Sru if (current_slant != slant) { 1196114402Sru put("x Slant "); 1197114402Sru put(slant); 1198114402Sru put('\n'); 1199114402Sru current_slant = slant; 1200114402Sru } 1201114402Sru int height = tf->get_height(); 1202114402Sru if (current_height != height) { 1203114402Sru put("x Height "); 1204114402Sru put(height == 0 ? current_size : height); 1205114402Sru put('\n'); 1206114402Sru current_height = height; 1207114402Sru } 1208114402Sru current_tfont = tf; 1209114402Sru} 1210114402Sru 1211114402Sru// fill_color calls `flush_tbuf' and `do_motion' if necessary. 1212114402Sru 1213114402Sruvoid troff_output_file::fill_color(color *col) 1214114402Sru{ 1215114402Sru if (!col || current_fill_color == col) 1216114402Sru return; 1217114402Sru current_fill_color = col; 1218114402Sru if (!color_flag) 1219114402Sru return; 1220114402Sru flush_tbuf(); 1221114402Sru do_motion(); 1222114402Sru put("DF"); 1223114402Sru unsigned int components[4]; 1224114402Sru color_scheme cs; 1225114402Sru cs = col->get_components(components); 1226114402Sru switch (cs) { 1227114402Sru case DEFAULT: 1228114402Sru put('d'); 1229114402Sru break; 1230114402Sru case RGB: 1231114402Sru put("r "); 1232114402Sru put(Red); 1233114402Sru put(' '); 1234114402Sru put(Green); 1235114402Sru put(' '); 1236114402Sru put(Blue); 1237114402Sru break; 1238114402Sru case CMY: 1239114402Sru put("c "); 1240114402Sru put(Cyan); 1241114402Sru put(' '); 1242114402Sru put(Magenta); 1243114402Sru put(' '); 1244114402Sru put(Yellow); 1245114402Sru break; 1246114402Sru case CMYK: 1247114402Sru put("k "); 1248114402Sru put(Cyan); 1249114402Sru put(' '); 1250114402Sru put(Magenta); 1251114402Sru put(' '); 1252114402Sru put(Yellow); 1253114402Sru put(' '); 1254114402Sru put(Black); 1255114402Sru break; 1256114402Sru case GRAY: 1257114402Sru put("g "); 1258114402Sru put(Gray); 1259114402Sru break; 1260114402Sru } 1261114402Sru put('\n'); 1262114402Sru} 1263114402Sru 1264114402Sru// glyph_color calls `flush_tbuf' and `do_motion' if necessary. 1265114402Sru 1266114402Sruvoid troff_output_file::glyph_color(color *col) 1267114402Sru{ 1268114402Sru if (!col || current_glyph_color == col) 1269114402Sru return; 1270114402Sru current_glyph_color = col; 1271114402Sru if (!color_flag) 1272114402Sru return; 1273114402Sru flush_tbuf(); 1274114402Sru // grotty doesn't like a color command if the vertical position is zero. 1275114402Sru do_motion(); 1276114402Sru put("m"); 1277114402Sru unsigned int components[4]; 1278114402Sru color_scheme cs; 1279114402Sru cs = col->get_components(components); 1280114402Sru switch (cs) { 1281114402Sru case DEFAULT: 1282114402Sru put('d'); 1283114402Sru break; 1284114402Sru case RGB: 1285114402Sru put("r "); 1286114402Sru put(Red); 1287114402Sru put(' '); 1288114402Sru put(Green); 1289114402Sru put(' '); 1290114402Sru put(Blue); 1291114402Sru break; 1292114402Sru case CMY: 1293114402Sru put("c "); 1294114402Sru put(Cyan); 1295114402Sru put(' '); 1296114402Sru put(Magenta); 1297114402Sru put(' '); 1298114402Sru put(Yellow); 1299114402Sru break; 1300114402Sru case CMYK: 1301114402Sru put("k "); 1302114402Sru put(Cyan); 1303114402Sru put(' '); 1304114402Sru put(Magenta); 1305114402Sru put(' '); 1306114402Sru put(Yellow); 1307114402Sru put(' '); 1308114402Sru put(Black); 1309114402Sru break; 1310114402Sru case GRAY: 1311114402Sru put("g "); 1312114402Sru put(Gray); 1313114402Sru break; 1314114402Sru } 1315114402Sru put('\n'); 1316114402Sru} 1317114402Sru 1318151497Sruvoid troff_output_file::add_to_tag_list(string s) 1319151497Sru{ 1320151497Sru if (tag_list == string("")) 1321151497Sru tag_list = s; 1322151497Sru else { 1323151497Sru tag_list += string("\n"); 1324151497Sru tag_list += s; 1325151497Sru } 1326151497Sru} 1327151497Sru 1328114402Sru// determine_line_limits - works out the smallest box which will contain 1329114402Sru// the entity, code, built from the point array. 1330114402Sruvoid troff_output_file::determine_line_limits(char code, hvpair *point, 1331114402Sru int npoints) 1332114402Sru{ 1333114402Sru int i, x, y; 1334114402Sru 1335114402Sru if (!is_on()) 1336114402Sru return; 1337114402Sru 1338114402Sru switch (code) { 1339114402Sru case 'c': 1340114402Sru case 'C': 1341114402Sru // only the h field is used when defining a circle 1342114402Sru check_output_limits(output_hpos, 1343114402Sru output_vpos - point[0].h.to_units()/2); 1344114402Sru check_output_limits(output_hpos + point[0].h.to_units(), 1345114402Sru output_vpos + point[0].h.to_units()/2); 1346114402Sru break; 1347114402Sru case 'E': 1348114402Sru case 'e': 1349114402Sru check_output_limits(output_hpos, 1350114402Sru output_vpos - point[0].v.to_units()/2); 1351114402Sru check_output_limits(output_hpos + point[0].h.to_units(), 1352114402Sru output_vpos + point[0].v.to_units()/2); 1353114402Sru break; 1354114402Sru case 'P': 1355114402Sru case 'p': 1356114402Sru x = output_hpos; 1357114402Sru y = output_vpos; 1358114402Sru check_output_limits(x, y); 1359114402Sru for (i = 0; i < npoints; i++) { 1360114402Sru x += point[i].h.to_units(); 1361114402Sru y += point[i].v.to_units(); 1362114402Sru check_output_limits(x, y); 1363114402Sru } 1364114402Sru break; 1365114402Sru case 't': 1366114402Sru x = output_hpos; 1367114402Sru y = output_vpos; 1368114402Sru for (i = 0; i < npoints; i++) { 1369114402Sru x += point[i].h.to_units(); 1370114402Sru y += point[i].v.to_units(); 1371114402Sru check_output_limits(x, y); 1372114402Sru } 1373114402Sru break; 1374114402Sru case 'a': 1375114402Sru double c[2]; 1376114402Sru int p[4]; 1377114402Sru int minx, miny, maxx, maxy; 1378114402Sru x = output_hpos; 1379114402Sru y = output_vpos; 1380114402Sru p[0] = point[0].h.to_units(); 1381114402Sru p[1] = point[0].v.to_units(); 1382114402Sru p[2] = point[1].h.to_units(); 1383114402Sru p[3] = point[1].v.to_units(); 1384114402Sru if (adjust_arc_center(p, c)) { 1385114402Sru check_output_arc_limits(x, y, 1386114402Sru p[0], p[1], p[2], p[3], 1387114402Sru c[0], c[1], 1388114402Sru &minx, &maxx, &miny, &maxy); 1389114402Sru check_output_limits(minx, miny); 1390114402Sru check_output_limits(maxx, maxy); 1391114402Sru break; 1392114402Sru } 1393114402Sru // fall through 1394114402Sru case 'l': 1395114402Sru x = output_hpos; 1396114402Sru y = output_vpos; 1397114402Sru check_output_limits(x, y); 1398114402Sru for (i = 0; i < npoints; i++) { 1399114402Sru x += point[i].h.to_units(); 1400114402Sru y += point[i].v.to_units(); 1401114402Sru check_output_limits(x, y); 1402114402Sru } 1403114402Sru break; 1404114402Sru default: 1405114402Sru x = output_hpos; 1406114402Sru y = output_vpos; 1407114402Sru for (i = 0; i < npoints; i++) { 1408114402Sru x += point[i].h.to_units(); 1409114402Sru y += point[i].v.to_units(); 1410114402Sru check_output_limits(x, y); 1411114402Sru } 1412114402Sru } 1413114402Sru} 1414114402Sru 1415114402Sruvoid troff_output_file::draw(char code, hvpair *point, int npoints, 1416114402Sru font_size fsize, color *gcol, color *fcol) 1417114402Sru{ 1418114402Sru int i; 1419114402Sru glyph_color(gcol); 1420114402Sru fill_color(fcol); 1421114402Sru flush_tbuf(); 1422114402Sru do_motion(); 1423114402Sru if (is_on()) { 1424114402Sru int size = fsize.to_scaled_points(); 1425114402Sru if (current_size != size) { 1426114402Sru put('s'); 1427114402Sru put(size); 1428114402Sru put('\n'); 1429114402Sru current_size = size; 1430114402Sru current_tfont = 0; 1431114402Sru } 1432114402Sru put('D'); 1433114402Sru put(code); 1434114402Sru if (code == 'c') { 1435114402Sru put(' '); 1436114402Sru put(point[0].h.to_units()); 1437114402Sru } 1438114402Sru else 1439114402Sru for (i = 0; i < npoints; i++) { 1440114402Sru put(' '); 1441114402Sru put(point[i].h.to_units()); 1442114402Sru put(' '); 1443114402Sru put(point[i].v.to_units()); 1444114402Sru } 1445114402Sru determine_line_limits(code, point, npoints); 1446114402Sru } 1447114402Sru 1448114402Sru for (i = 0; i < npoints; i++) 1449114402Sru output_hpos += point[i].h.to_units(); 1450114402Sru hpos = output_hpos; 1451114402Sru if (code != 'e') { 1452114402Sru for (i = 0; i < npoints; i++) 1453114402Sru output_vpos += point[i].v.to_units(); 1454114402Sru vpos = output_vpos; 1455114402Sru } 1456114402Sru if (is_on()) 1457114402Sru put('\n'); 1458114402Sru} 1459114402Sru 1460114402Sruvoid troff_output_file::really_on() 1461114402Sru{ 1462114402Sru flush_tbuf(); 1463114402Sru force_motion = 1; 1464114402Sru do_motion(); 1465114402Sru} 1466114402Sru 1467114402Sruvoid troff_output_file::really_off() 1468114402Sru{ 1469114402Sru flush_tbuf(); 1470114402Sru} 1471114402Sru 1472114402Sruvoid troff_output_file::really_put_filename(const char *filename) 1473114402Sru{ 1474114402Sru flush_tbuf(); 1475114402Sru put("F "); 1476114402Sru put(filename); 1477114402Sru put('\n'); 1478114402Sru} 1479114402Sru 1480114402Sruvoid troff_output_file::really_begin_page(int pageno, vunits page_length) 1481114402Sru{ 1482114402Sru flush_tbuf(); 1483114402Sru if (begun_page) { 1484114402Sru if (page_length > V0) { 1485114402Sru put('V'); 1486114402Sru put(page_length.to_units()); 1487114402Sru put('\n'); 1488114402Sru } 1489114402Sru } 1490114402Sru else 1491114402Sru begun_page = 1; 1492114402Sru current_tfont = 0; 1493114402Sru current_font_number = -1; 1494114402Sru current_size = 0; 1495114402Sru // current_height = 0; 1496114402Sru // current_slant = 0; 1497114402Sru hpos = 0; 1498114402Sru vpos = 0; 1499114402Sru output_hpos = 0; 1500114402Sru output_vpos = 0; 1501114402Sru force_motion = 1; 1502114402Sru for (int i = 0; i < nfont_positions; i++) 1503114402Sru font_position[i] = NULL_SYMBOL; 1504114402Sru put('p'); 1505114402Sru put(pageno); 1506114402Sru put('\n'); 1507114402Sru} 1508114402Sru 1509151497Sruvoid troff_output_file::really_copy_file(hunits x, vunits y, 1510151497Sru const char *filename) 1511114402Sru{ 1512114402Sru moveto(x, y); 1513114402Sru flush_tbuf(); 1514114402Sru do_motion(); 1515114402Sru errno = 0; 1516151497Sru FILE *ifp = include_search_path.open_file_cautious(filename); 1517114402Sru if (ifp == 0) 1518114402Sru error("can't open `%1': %2", filename, strerror(errno)); 1519114402Sru else { 1520114402Sru int c; 1521114402Sru while ((c = getc(ifp)) != EOF) 1522114402Sru put(char(c)); 1523114402Sru fclose(ifp); 1524114402Sru } 1525114402Sru force_motion = 1; 1526114402Sru current_size = 0; 1527114402Sru current_tfont = 0; 1528114402Sru current_font_number = -1; 1529114402Sru for (int i = 0; i < nfont_positions; i++) 1530114402Sru font_position[i] = NULL_SYMBOL; 1531114402Sru} 1532114402Sru 1533114402Sruvoid troff_output_file::really_transparent_char(unsigned char c) 1534114402Sru{ 1535114402Sru put(c); 1536114402Sru} 1537114402Sru 1538114402Srutroff_output_file::~troff_output_file() 1539114402Sru{ 1540114402Sru a_delete font_position; 1541114402Sru} 1542114402Sru 1543114402Sruvoid troff_output_file::trailer(vunits page_length) 1544114402Sru{ 1545114402Sru flush_tbuf(); 1546114402Sru if (page_length > V0) { 1547114402Sru put("x trailer\n"); 1548114402Sru put('V'); 1549114402Sru put(page_length.to_units()); 1550114402Sru put('\n'); 1551114402Sru } 1552114402Sru put("x stop\n"); 1553114402Sru} 1554114402Sru 1555114402Srutroff_output_file::troff_output_file() 1556114402Sru: current_slant(0), current_height(0), current_fill_color(0), 1557151497Sru current_glyph_color(0), nfont_positions(10), tbuf_len(0), begun_page(0), 1558151497Sru cur_div_level(0) 1559114402Sru{ 1560114402Sru font_position = new symbol[nfont_positions]; 1561114402Sru put("x T "); 1562114402Sru put(device); 1563114402Sru put('\n'); 1564114402Sru put("x res "); 1565114402Sru put(units_per_inch); 1566114402Sru put(' '); 1567114402Sru put(hresolution); 1568114402Sru put(' '); 1569114402Sru put(vresolution); 1570114402Sru put('\n'); 1571114402Sru put("x init\n"); 1572114402Sru} 1573114402Sru 1574114402Sru/* output_file */ 1575114402Sru 1576114402Sruoutput_file *the_output = 0; 1577114402Sru 1578114402Sruoutput_file::output_file() 1579114402Sru{ 1580114402Sru} 1581114402Sru 1582114402Sruoutput_file::~output_file() 1583114402Sru{ 1584114402Sru} 1585114402Sru 1586114402Sruvoid output_file::trailer(vunits) 1587114402Sru{ 1588114402Sru} 1589114402Sru 1590114402Sruvoid output_file::put_filename(const char *) 1591114402Sru{ 1592114402Sru} 1593114402Sru 1594114402Sruvoid output_file::on() 1595114402Sru{ 1596114402Sru} 1597114402Sru 1598114402Sruvoid output_file::off() 1599114402Sru{ 1600114402Sru} 1601114402Sru 1602114402Srureal_output_file::real_output_file() 1603114402Sru: printing(0), output_on(1) 1604114402Sru{ 1605114402Sru#ifndef POPEN_MISSING 1606114402Sru if (pipe_command) { 1607114402Sru if ((fp = popen(pipe_command, POPEN_WT)) != 0) { 1608114402Sru piped = 1; 1609114402Sru return; 1610114402Sru } 1611114402Sru error("pipe open failed: %1", strerror(errno)); 1612114402Sru } 1613114402Sru piped = 0; 1614114402Sru#endif /* not POPEN_MISSING */ 1615114402Sru fp = stdout; 1616114402Sru} 1617114402Sru 1618114402Srureal_output_file::~real_output_file() 1619114402Sru{ 1620114402Sru if (!fp) 1621114402Sru return; 1622114402Sru // To avoid looping, set fp to 0 before calling fatal(). 1623114402Sru if (ferror(fp) || fflush(fp) < 0) { 1624114402Sru fp = 0; 1625114402Sru fatal("error writing output file"); 1626114402Sru } 1627114402Sru#ifndef POPEN_MISSING 1628114402Sru if (piped) { 1629114402Sru int result = pclose(fp); 1630114402Sru fp = 0; 1631114402Sru if (result < 0) 1632114402Sru fatal("pclose failed"); 1633114402Sru if (!WIFEXITED(result)) 1634114402Sru error("output process `%1' got fatal signal %2", 1635114402Sru pipe_command, 1636114402Sru WIFSIGNALED(result) ? WTERMSIG(result) : WSTOPSIG(result)); 1637114402Sru else { 1638114402Sru int exit_status = WEXITSTATUS(result); 1639114402Sru if (exit_status != 0) 1640114402Sru error("output process `%1' exited with status %2", 1641114402Sru pipe_command, exit_status); 1642114402Sru } 1643114402Sru } 1644114402Sru else 1645114402Sru#endif /* not POPEN MISSING */ 1646114402Sru if (fclose(fp) < 0) { 1647114402Sru fp = 0; 1648114402Sru fatal("error closing output file"); 1649114402Sru } 1650114402Sru} 1651114402Sru 1652114402Sruvoid real_output_file::flush() 1653114402Sru{ 1654114402Sru if (fflush(fp) < 0) 1655114402Sru fatal("error writing output file"); 1656114402Sru} 1657114402Sru 1658114402Sruint real_output_file::is_printing() 1659114402Sru{ 1660114402Sru return printing; 1661114402Sru} 1662114402Sru 1663114402Sruvoid real_output_file::begin_page(int pageno, vunits page_length) 1664114402Sru{ 1665114402Sru printing = in_output_page_list(pageno); 1666114402Sru if (printing) 1667114402Sru really_begin_page(pageno, page_length); 1668114402Sru} 1669114402Sru 1670114402Sruvoid real_output_file::copy_file(hunits x, vunits y, const char *filename) 1671114402Sru{ 1672114402Sru if (printing && output_on) 1673114402Sru really_copy_file(x, y, filename); 1674114402Sru check_output_limits(x.to_units(), y.to_units()); 1675114402Sru} 1676114402Sru 1677114402Sruvoid real_output_file::transparent_char(unsigned char c) 1678114402Sru{ 1679114402Sru if (printing && output_on) 1680114402Sru really_transparent_char(c); 1681114402Sru} 1682114402Sru 1683114402Sruvoid real_output_file::print_line(hunits x, vunits y, node *n, 1684114402Sru vunits before, vunits after, hunits width) 1685114402Sru{ 1686114402Sru if (printing) 1687114402Sru really_print_line(x, y, n, before, after, width); 1688114402Sru delete_node_list(n); 1689114402Sru} 1690114402Sru 1691114402Sruvoid real_output_file::really_copy_file(hunits, vunits, const char *) 1692114402Sru{ 1693114402Sru // do nothing 1694114402Sru} 1695114402Sru 1696114402Sruvoid real_output_file::put_filename(const char *filename) 1697114402Sru{ 1698114402Sru really_put_filename(filename); 1699114402Sru} 1700114402Sru 1701114402Sruvoid real_output_file::really_put_filename(const char *) 1702114402Sru{ 1703114402Sru} 1704114402Sru 1705114402Sruvoid real_output_file::on() 1706114402Sru{ 1707114402Sru really_on(); 1708114402Sru if (output_on == 0) 1709114402Sru output_on = 1; 1710114402Sru} 1711114402Sru 1712114402Sruvoid real_output_file::off() 1713114402Sru{ 1714114402Sru really_off(); 1715114402Sru output_on = 0; 1716114402Sru} 1717114402Sru 1718114402Sruint real_output_file::is_on() 1719114402Sru{ 1720114402Sru return output_on; 1721114402Sru} 1722114402Sru 1723114402Sruvoid real_output_file::really_on() 1724114402Sru{ 1725114402Sru} 1726114402Sru 1727114402Sruvoid real_output_file::really_off() 1728114402Sru{ 1729114402Sru} 1730114402Sru 1731114402Sru/* ascii_output_file */ 1732114402Sru 1733114402Sruvoid ascii_output_file::really_transparent_char(unsigned char c) 1734114402Sru{ 1735114402Sru putc(c, fp); 1736114402Sru} 1737114402Sru 1738114402Sruvoid ascii_output_file::really_print_line(hunits, vunits, node *n, 1739114402Sru vunits, vunits, hunits) 1740114402Sru{ 1741114402Sru while (n != 0) { 1742114402Sru n->ascii_print(this); 1743114402Sru n = n->next; 1744114402Sru } 1745114402Sru fputc('\n', fp); 1746114402Sru} 1747114402Sru 1748114402Sruvoid ascii_output_file::really_begin_page(int /*pageno*/, vunits /*page_length*/) 1749114402Sru{ 1750114402Sru fputs("<beginning of page>\n", fp); 1751114402Sru} 1752114402Sru 1753114402Sruascii_output_file::ascii_output_file() 1754114402Sru{ 1755114402Sru} 1756114402Sru 1757114402Sru/* suppress_output_file */ 1758114402Sru 1759114402Srusuppress_output_file::suppress_output_file() 1760114402Sru{ 1761114402Sru} 1762114402Sru 1763114402Sruvoid suppress_output_file::really_print_line(hunits, vunits, node *, vunits, vunits, hunits) 1764114402Sru{ 1765114402Sru} 1766114402Sru 1767114402Sruvoid suppress_output_file::really_begin_page(int, vunits) 1768114402Sru{ 1769114402Sru} 1770114402Sru 1771114402Sruvoid suppress_output_file::really_transparent_char(unsigned char) 1772114402Sru{ 1773114402Sru} 1774114402Sru 1775114402Sru/* glyphs, ligatures, kerns, discretionary breaks */ 1776114402Sru 1777114402Sruclass charinfo_node : public node { 1778114402Sruprotected: 1779114402Sru charinfo *ci; 1780114402Srupublic: 1781151497Sru charinfo_node(charinfo *, statem *, int, node * = 0); 1782114402Sru int ends_sentence(); 1783114402Sru int overlaps_vertically(); 1784114402Sru int overlaps_horizontally(); 1785114402Sru}; 1786114402Sru 1787151497Srucharinfo_node::charinfo_node(charinfo *c, statem *s, int pop, node *x) 1788151497Sru: node(x, s, pop), ci(c) 1789114402Sru{ 1790114402Sru} 1791114402Sru 1792114402Sruint charinfo_node::ends_sentence() 1793114402Sru{ 1794114402Sru if (ci->ends_sentence()) 1795114402Sru return 1; 1796114402Sru else if (ci->transparent()) 1797114402Sru return 2; 1798114402Sru else 1799114402Sru return 0; 1800114402Sru} 1801114402Sru 1802114402Sruint charinfo_node::overlaps_horizontally() 1803114402Sru{ 1804114402Sru return ci->overlaps_horizontally(); 1805114402Sru} 1806114402Sru 1807114402Sruint charinfo_node::overlaps_vertically() 1808114402Sru{ 1809114402Sru return ci->overlaps_vertically(); 1810114402Sru} 1811114402Sru 1812114402Sruclass glyph_node : public charinfo_node { 1813114402Sru static glyph_node *free_list; 1814114402Sruprotected: 1815114402Sru tfont *tf; 1816114402Sru color *gcol; 1817114402Sru color *fcol; /* this is needed for grotty */ 1818114402Sru#ifdef STORE_WIDTH 1819114402Sru hunits wid; 1820151497Sru glyph_node(charinfo *, tfont *, color *, color *, hunits, 1821151497Sru statem *, int, node * = 0); 1822114402Sru#endif 1823114402Srupublic: 1824114402Sru void *operator new(size_t); 1825114402Sru void operator delete(void *); 1826151497Sru glyph_node(charinfo *, tfont *, color *, color *, 1827151497Sru statem *, int, node * = 0); 1828114402Sru ~glyph_node() {} 1829114402Sru node *copy(); 1830114402Sru node *merge_glyph_node(glyph_node *); 1831114402Sru node *merge_self(node *); 1832114402Sru hunits width(); 1833114402Sru node *last_char_node(); 1834114402Sru units size(); 1835114402Sru void vertical_extent(vunits *, vunits *); 1836114402Sru hunits subscript_correction(); 1837114402Sru hunits italic_correction(); 1838114402Sru hunits left_italic_correction(); 1839114402Sru hunits skew(); 1840114402Sru hyphenation_type get_hyphenation_type(); 1841114402Sru tfont *get_tfont(); 1842114402Sru color *get_glyph_color(); 1843114402Sru color *get_fill_color(); 1844114402Sru void tprint(troff_output_file *); 1845114402Sru void zero_width_tprint(troff_output_file *); 1846114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 1847114402Sru node *add_self(node *, hyphen_list **); 1848114402Sru void ascii_print(ascii_output_file *); 1849114402Sru void asciify(macro *); 1850114402Sru int character_type(); 1851114402Sru int same(node *); 1852114402Sru const char *type(); 1853114402Sru int force_tprint(); 1854151497Sru int is_tag(); 1855151497Sru void debug_node(); 1856114402Sru}; 1857114402Sru 1858114402Sruglyph_node *glyph_node::free_list = 0; 1859114402Sru 1860114402Sruclass ligature_node : public glyph_node { 1861114402Sru node *n1; 1862114402Sru node *n2; 1863114402Sru#ifdef STORE_WIDTH 1864114402Sru ligature_node(charinfo *, tfont *, color *, color *, hunits, 1865151497Sru node *, node *, statem *, int, node * = 0); 1866114402Sru#endif 1867114402Srupublic: 1868114402Sru void *operator new(size_t); 1869114402Sru void operator delete(void *); 1870114402Sru ligature_node(charinfo *, tfont *, color *, color *, 1871151497Sru node *, node *, statem *, int, node * = 0); 1872114402Sru ~ligature_node(); 1873114402Sru node *copy(); 1874114402Sru node *add_self(node *, hyphen_list **); 1875114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 1876114402Sru void ascii_print(ascii_output_file *); 1877114402Sru void asciify(macro *); 1878114402Sru int same(node *); 1879114402Sru const char *type(); 1880114402Sru int force_tprint(); 1881151497Sru int is_tag(); 1882114402Sru}; 1883114402Sru 1884114402Sruclass kern_pair_node : public node { 1885114402Sru hunits amount; 1886114402Sru node *n1; 1887114402Sru node *n2; 1888114402Srupublic: 1889151497Sru kern_pair_node(hunits, node *, node *, statem *, int, node * = 0); 1890114402Sru ~kern_pair_node(); 1891114402Sru node *copy(); 1892114402Sru node *merge_glyph_node(glyph_node *); 1893114402Sru node *add_self(node *, hyphen_list **); 1894114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 1895114402Sru node *add_discretionary_hyphen(); 1896114402Sru hunits width(); 1897114402Sru node *last_char_node(); 1898114402Sru hunits italic_correction(); 1899114402Sru hunits subscript_correction(); 1900114402Sru void tprint(troff_output_file *); 1901114402Sru hyphenation_type get_hyphenation_type(); 1902114402Sru int ends_sentence(); 1903114402Sru void ascii_print(ascii_output_file *); 1904114402Sru void asciify(macro *); 1905114402Sru int same(node *); 1906114402Sru const char *type(); 1907114402Sru int force_tprint(); 1908151497Sru int is_tag(); 1909114402Sru void vertical_extent(vunits *, vunits *); 1910114402Sru}; 1911114402Sru 1912114402Sruclass dbreak_node : public node { 1913114402Sru node *none; 1914114402Sru node *pre; 1915114402Sru node *post; 1916114402Srupublic: 1917151497Sru dbreak_node(node *, node *, statem *, int, node * = 0); 1918114402Sru ~dbreak_node(); 1919114402Sru node *copy(); 1920114402Sru node *merge_glyph_node(glyph_node *); 1921114402Sru node *add_discretionary_hyphen(); 1922114402Sru hunits width(); 1923114402Sru node *last_char_node(); 1924114402Sru hunits italic_correction(); 1925114402Sru hunits subscript_correction(); 1926114402Sru void tprint(troff_output_file *); 1927114402Sru breakpoint *get_breakpoints(hunits width, int ns, breakpoint *rest = 0, 1928114402Sru int is_inner = 0); 1929114402Sru int nbreaks(); 1930114402Sru int ends_sentence(); 1931114402Sru void split(int, node **, node **); 1932114402Sru hyphenation_type get_hyphenation_type(); 1933114402Sru void ascii_print(ascii_output_file *); 1934114402Sru void asciify(macro *); 1935114402Sru int same(node *); 1936114402Sru const char *type(); 1937114402Sru int force_tprint(); 1938151497Sru int is_tag(); 1939114402Sru}; 1940114402Sru 1941114402Sruvoid *glyph_node::operator new(size_t n) 1942114402Sru{ 1943114402Sru assert(n == sizeof(glyph_node)); 1944114402Sru if (!free_list) { 1945114402Sru const int BLOCK = 1024; 1946114402Sru free_list = (glyph_node *)new char[sizeof(glyph_node)*BLOCK]; 1947114402Sru for (int i = 0; i < BLOCK - 1; i++) 1948114402Sru free_list[i].next = free_list + i + 1; 1949114402Sru free_list[BLOCK-1].next = 0; 1950114402Sru } 1951114402Sru glyph_node *p = free_list; 1952114402Sru free_list = (glyph_node *)(free_list->next); 1953114402Sru p->next = 0; 1954114402Sru return p; 1955114402Sru} 1956114402Sru 1957114402Sruvoid *ligature_node::operator new(size_t n) 1958114402Sru{ 1959114402Sru return new char[n]; 1960114402Sru} 1961114402Sru 1962114402Sruvoid glyph_node::operator delete(void *p) 1963114402Sru{ 1964114402Sru if (p) { 1965114402Sru ((glyph_node *)p)->next = free_list; 1966114402Sru free_list = (glyph_node *)p; 1967114402Sru } 1968114402Sru} 1969114402Sru 1970114402Sruvoid ligature_node::operator delete(void *p) 1971114402Sru{ 1972114402Sru delete[] (char *)p; 1973114402Sru} 1974114402Sru 1975151497Sruglyph_node::glyph_node(charinfo *c, tfont *t, color *gc, color *fc, 1976151497Sru statem *s, int pop, node *x) 1977151497Sru: charinfo_node(c, s, pop, x), tf(t), gcol(gc), fcol(fc) 1978114402Sru{ 1979114402Sru#ifdef STORE_WIDTH 1980114402Sru wid = tf->get_width(ci); 1981114402Sru#endif 1982114402Sru} 1983114402Sru 1984114402Sru#ifdef STORE_WIDTH 1985114402Sruglyph_node::glyph_node(charinfo *c, tfont *t, 1986151497Sru color *gc, color *fc, hunits w, 1987151497Sru statem *s, int pop, node *x) 1988151497Sru: charinfo_node(c, s, pop, x), tf(t), gcol(gc), fcol(fc), wid(w) 1989114402Sru{ 1990114402Sru} 1991114402Sru#endif 1992114402Sru 1993114402Srunode *glyph_node::copy() 1994114402Sru{ 1995114402Sru#ifdef STORE_WIDTH 1996151497Sru return new glyph_node(ci, tf, gcol, fcol, wid, state, div_nest_level); 1997114402Sru#else 1998151497Sru return new glyph_node(ci, tf, gcol, fcol, state, div_nest_level); 1999114402Sru#endif 2000114402Sru} 2001114402Sru 2002114402Srunode *glyph_node::merge_self(node *nd) 2003114402Sru{ 2004114402Sru return nd->merge_glyph_node(this); 2005114402Sru} 2006114402Sru 2007114402Sruint glyph_node::character_type() 2008114402Sru{ 2009114402Sru return tf->get_character_type(ci); 2010114402Sru} 2011114402Sru 2012114402Srunode *glyph_node::add_self(node *n, hyphen_list **p) 2013114402Sru{ 2014114402Sru assert(ci->get_hyphenation_code() == (*p)->hyphenation_code); 2015114402Sru next = 0; 2016114402Sru node *nn; 2017114402Sru if (n == 0 || (nn = n->merge_glyph_node(this)) == 0) { 2018114402Sru next = n; 2019114402Sru nn = this; 2020114402Sru } 2021114402Sru if ((*p)->hyphen) 2022114402Sru nn = nn->add_discretionary_hyphen(); 2023114402Sru hyphen_list *pp = *p; 2024114402Sru *p = (*p)->next; 2025114402Sru delete pp; 2026114402Sru return nn; 2027114402Sru} 2028114402Sru 2029114402Sruunits glyph_node::size() 2030114402Sru{ 2031114402Sru return tf->get_size().to_units(); 2032114402Sru} 2033114402Sru 2034114402Sruhyphen_list *glyph_node::get_hyphen_list(hyphen_list *tail, int *count) 2035114402Sru{ 2036114402Sru (*count)++; 2037114402Sru return new hyphen_list(ci->get_hyphenation_code(), tail); 2038114402Sru} 2039114402Sru 2040114402Srutfont *node::get_tfont() 2041114402Sru{ 2042114402Sru return 0; 2043114402Sru} 2044114402Sru 2045114402Srutfont *glyph_node::get_tfont() 2046114402Sru{ 2047114402Sru return tf; 2048114402Sru} 2049114402Sru 2050114402Srucolor *node::get_glyph_color() 2051114402Sru{ 2052114402Sru return 0; 2053114402Sru} 2054114402Sru 2055114402Srucolor *glyph_node::get_glyph_color() 2056114402Sru{ 2057114402Sru return gcol; 2058114402Sru} 2059114402Sru 2060114402Srucolor *node::get_fill_color() 2061114402Sru{ 2062114402Sru return 0; 2063114402Sru} 2064114402Sru 2065114402Srucolor *glyph_node::get_fill_color() 2066114402Sru{ 2067114402Sru return fcol; 2068114402Sru} 2069114402Sru 2070114402Srunode *node::merge_glyph_node(glyph_node *) 2071114402Sru{ 2072114402Sru return 0; 2073114402Sru} 2074114402Sru 2075114402Srunode *glyph_node::merge_glyph_node(glyph_node *gn) 2076114402Sru{ 2077114402Sru if (tf == gn->tf && gcol == gn->gcol && fcol == gn->fcol) { 2078114402Sru charinfo *lig; 2079114402Sru if ((lig = tf->get_lig(ci, gn->ci)) != 0) { 2080114402Sru node *next1 = next; 2081114402Sru next = 0; 2082151497Sru return new ligature_node(lig, tf, gcol, fcol, this, gn, state, 2083151497Sru gn->div_nest_level, next1); 2084114402Sru } 2085114402Sru hunits kern; 2086114402Sru if (tf->get_kern(ci, gn->ci, &kern)) { 2087114402Sru node *next1 = next; 2088114402Sru next = 0; 2089151497Sru return new kern_pair_node(kern, this, gn, state, 2090151497Sru gn->div_nest_level, next1); 2091114402Sru } 2092114402Sru } 2093114402Sru return 0; 2094114402Sru} 2095114402Sru 2096114402Sru#ifdef STORE_WIDTH 2097114402Sruinline 2098114402Sru#endif 2099114402Sruhunits glyph_node::width() 2100114402Sru{ 2101114402Sru#ifdef STORE_WIDTH 2102114402Sru return wid; 2103114402Sru#else 2104114402Sru return tf->get_width(ci); 2105114402Sru#endif 2106114402Sru} 2107114402Sru 2108114402Srunode *glyph_node::last_char_node() 2109114402Sru{ 2110114402Sru return this; 2111114402Sru} 2112114402Sru 2113114402Sruvoid glyph_node::vertical_extent(vunits *min, vunits *max) 2114114402Sru{ 2115114402Sru *min = -tf->get_char_height(ci); 2116114402Sru *max = tf->get_char_depth(ci); 2117114402Sru} 2118114402Sru 2119114402Sruhunits glyph_node::skew() 2120114402Sru{ 2121114402Sru return tf->get_char_skew(ci); 2122114402Sru} 2123114402Sru 2124114402Sruhunits glyph_node::subscript_correction() 2125114402Sru{ 2126114402Sru return tf->get_subscript_correction(ci); 2127114402Sru} 2128114402Sru 2129114402Sruhunits glyph_node::italic_correction() 2130114402Sru{ 2131114402Sru return tf->get_italic_correction(ci); 2132114402Sru} 2133114402Sru 2134114402Sruhunits glyph_node::left_italic_correction() 2135114402Sru{ 2136114402Sru return tf->get_left_italic_correction(ci); 2137114402Sru} 2138114402Sru 2139114402Sruhyphenation_type glyph_node::get_hyphenation_type() 2140114402Sru{ 2141114402Sru return HYPHEN_MIDDLE; 2142114402Sru} 2143114402Sru 2144114402Sruvoid glyph_node::ascii_print(ascii_output_file *ascii) 2145114402Sru{ 2146114402Sru unsigned char c = ci->get_ascii_code(); 2147114402Sru if (c != 0) 2148114402Sru ascii->outc(c); 2149114402Sru else 2150114402Sru ascii->outs(ci->nm.contents()); 2151114402Sru} 2152114402Sru 2153151497Sruvoid glyph_node::debug_node() 2154151497Sru{ 2155151497Sru unsigned char c = ci->get_ascii_code(); 2156151497Sru fprintf(stderr, "{ %s [", type()); 2157151497Sru if (c) 2158151497Sru fprintf(stderr, "%c", c); 2159151497Sru else 2160222083Sbenl fputs(ci->nm.contents(), stderr); 2161151497Sru if (push_state) 2162151497Sru fprintf(stderr, " <push_state>"); 2163151497Sru if (state) 2164151497Sru state->display_state(); 2165151497Sru fprintf(stderr, " nest level %d", div_nest_level); 2166151497Sru fprintf(stderr, "]}\n"); 2167151497Sru fflush(stderr); 2168151497Sru} 2169151497Sru 2170114402Sruligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc, 2171151497Sru node *gn1, node *gn2, statem *s, 2172151497Sru int pop, node *x) 2173151497Sru: glyph_node(c, t, gc, fc, s, pop, x), n1(gn1), n2(gn2) 2174114402Sru{ 2175114402Sru} 2176114402Sru 2177114402Sru#ifdef STORE_WIDTH 2178114402Sruligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc, 2179151497Sru hunits w, node *gn1, node *gn2, statem *s, 2180151497Sru int pop, node *x) 2181151497Sru: glyph_node(c, t, gc, fc, w, s, pop, x), n1(gn1), n2(gn2) 2182114402Sru{ 2183114402Sru} 2184114402Sru#endif 2185114402Sru 2186114402Sruligature_node::~ligature_node() 2187114402Sru{ 2188114402Sru delete n1; 2189114402Sru delete n2; 2190114402Sru} 2191114402Sru 2192114402Srunode *ligature_node::copy() 2193114402Sru{ 2194114402Sru#ifdef STORE_WIDTH 2195151497Sru return new ligature_node(ci, tf, gcol, fcol, wid, n1->copy(), n2->copy(), 2196151497Sru state, div_nest_level); 2197114402Sru#else 2198151497Sru return new ligature_node(ci, tf, gcol, fcol, n1->copy(), n2->copy(), 2199151497Sru state, div_nest_level); 2200114402Sru#endif 2201114402Sru} 2202114402Sru 2203114402Sruvoid ligature_node::ascii_print(ascii_output_file *ascii) 2204114402Sru{ 2205114402Sru n1->ascii_print(ascii); 2206114402Sru n2->ascii_print(ascii); 2207114402Sru} 2208114402Sru 2209114402Sruhyphen_list *ligature_node::get_hyphen_list(hyphen_list *tail, int *count) 2210114402Sru{ 2211114402Sru hyphen_list *hl = n2->get_hyphen_list(tail, count); 2212114402Sru return n1->get_hyphen_list(hl, count); 2213114402Sru} 2214114402Sru 2215114402Srunode *ligature_node::add_self(node *n, hyphen_list **p) 2216114402Sru{ 2217114402Sru n = n1->add_self(n, p); 2218114402Sru n = n2->add_self(n, p); 2219114402Sru n1 = n2 = 0; 2220114402Sru delete this; 2221114402Sru return n; 2222114402Sru} 2223114402Sru 2224151497Srukern_pair_node::kern_pair_node(hunits n, node *first, node *second, 2225151497Sru statem* s, int pop, node *x) 2226151497Sru: node(x, s, pop), amount(n), n1(first), n2(second) 2227114402Sru{ 2228114402Sru} 2229114402Sru 2230151497Srudbreak_node::dbreak_node(node *n, node *p, statem *s, int pop, node *x) 2231151497Sru: node(x, s, pop), none(n), pre(p), post(0) 2232114402Sru{ 2233114402Sru} 2234114402Sru 2235114402Srunode *dbreak_node::merge_glyph_node(glyph_node *gn) 2236114402Sru{ 2237114402Sru glyph_node *gn2 = (glyph_node *)gn->copy(); 2238114402Sru node *new_none = none ? none->merge_glyph_node(gn) : 0; 2239114402Sru node *new_post = post ? post->merge_glyph_node(gn2) : 0; 2240114402Sru if (new_none == 0 && new_post == 0) { 2241114402Sru delete gn2; 2242114402Sru return 0; 2243114402Sru } 2244114402Sru if (new_none != 0) 2245114402Sru none = new_none; 2246114402Sru else { 2247114402Sru gn->next = none; 2248114402Sru none = gn; 2249114402Sru } 2250114402Sru if (new_post != 0) 2251114402Sru post = new_post; 2252114402Sru else { 2253114402Sru gn2->next = post; 2254114402Sru post = gn2; 2255114402Sru } 2256114402Sru return this; 2257114402Sru} 2258114402Sru 2259114402Srunode *kern_pair_node::merge_glyph_node(glyph_node *gn) 2260114402Sru{ 2261114402Sru node *nd = n2->merge_glyph_node(gn); 2262114402Sru if (nd == 0) 2263114402Sru return 0; 2264114402Sru n2 = nd; 2265114402Sru nd = n2->merge_self(n1); 2266114402Sru if (nd) { 2267114402Sru nd->next = next; 2268114402Sru n1 = 0; 2269114402Sru n2 = 0; 2270114402Sru delete this; 2271114402Sru return nd; 2272114402Sru } 2273114402Sru return this; 2274114402Sru} 2275114402Sru 2276114402Sruhunits kern_pair_node::italic_correction() 2277114402Sru{ 2278114402Sru return n2->italic_correction(); 2279114402Sru} 2280114402Sru 2281114402Sruhunits kern_pair_node::subscript_correction() 2282114402Sru{ 2283114402Sru return n2->subscript_correction(); 2284114402Sru} 2285114402Sru 2286114402Sruvoid kern_pair_node::vertical_extent(vunits *min, vunits *max) 2287114402Sru{ 2288114402Sru n1->vertical_extent(min, max); 2289114402Sru vunits min2, max2; 2290114402Sru n2->vertical_extent(&min2, &max2); 2291114402Sru if (min2 < *min) 2292114402Sru *min = min2; 2293114402Sru if (max2 > *max) 2294114402Sru *max = max2; 2295114402Sru} 2296114402Sru 2297114402Srunode *kern_pair_node::add_discretionary_hyphen() 2298114402Sru{ 2299114402Sru tfont *tf = n2->get_tfont(); 2300114402Sru if (tf) { 2301114402Sru if (tf->contains(soft_hyphen_char)) { 2302114402Sru color *gcol = n2->get_glyph_color(); 2303114402Sru color *fcol = n2->get_fill_color(); 2304114402Sru node *next1 = next; 2305114402Sru next = 0; 2306114402Sru node *n = copy(); 2307151497Sru glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol, 2308151497Sru state, div_nest_level); 2309114402Sru node *nn = n->merge_glyph_node(gn); 2310114402Sru if (nn == 0) { 2311114402Sru gn->next = n; 2312114402Sru nn = gn; 2313114402Sru } 2314151497Sru return new dbreak_node(this, nn, state, div_nest_level, next1); 2315114402Sru } 2316114402Sru } 2317114402Sru return this; 2318114402Sru} 2319114402Sru 2320114402Srukern_pair_node::~kern_pair_node() 2321114402Sru{ 2322114402Sru if (n1 != 0) 2323114402Sru delete n1; 2324114402Sru if (n2 != 0) 2325114402Sru delete n2; 2326114402Sru} 2327114402Sru 2328114402Srudbreak_node::~dbreak_node() 2329114402Sru{ 2330114402Sru delete_node_list(pre); 2331114402Sru delete_node_list(post); 2332114402Sru delete_node_list(none); 2333114402Sru} 2334114402Sru 2335114402Srunode *kern_pair_node::copy() 2336114402Sru{ 2337151497Sru return new kern_pair_node(amount, n1->copy(), n2->copy(), state, 2338151497Sru div_nest_level); 2339114402Sru} 2340114402Sru 2341114402Srunode *copy_node_list(node *n) 2342114402Sru{ 2343114402Sru node *p = 0; 2344114402Sru while (n != 0) { 2345114402Sru node *nn = n->copy(); 2346114402Sru nn->next = p; 2347114402Sru p = nn; 2348114402Sru n = n->next; 2349114402Sru } 2350114402Sru while (p != 0) { 2351114402Sru node *pp = p->next; 2352114402Sru p->next = n; 2353114402Sru n = p; 2354114402Sru p = pp; 2355114402Sru } 2356114402Sru return n; 2357114402Sru} 2358114402Sru 2359114402Sruvoid delete_node_list(node *n) 2360114402Sru{ 2361114402Sru while (n != 0) { 2362114402Sru node *tem = n; 2363114402Sru n = n->next; 2364114402Sru delete tem; 2365114402Sru } 2366114402Sru} 2367114402Sru 2368114402Srunode *dbreak_node::copy() 2369114402Sru{ 2370151497Sru dbreak_node *p = new dbreak_node(copy_node_list(none), copy_node_list(pre), 2371151497Sru state, div_nest_level); 2372114402Sru p->post = copy_node_list(post); 2373114402Sru return p; 2374114402Sru} 2375114402Sru 2376114402Sruhyphen_list *node::get_hyphen_list(hyphen_list *tail, int *) 2377114402Sru{ 2378114402Sru return tail; 2379114402Sru} 2380114402Sru 2381114402Sruhyphen_list *kern_pair_node::get_hyphen_list(hyphen_list *tail, int *count) 2382114402Sru{ 2383114402Sru hyphen_list *hl = n2->get_hyphen_list(tail, count); 2384114402Sru return n1->get_hyphen_list(hl, count); 2385114402Sru} 2386114402Sru 2387114402Sruclass hyphen_inhibitor_node : public node { 2388114402Srupublic: 2389151497Sru hyphen_inhibitor_node(node * = 0); 2390114402Sru node *copy(); 2391114402Sru int same(node *); 2392114402Sru const char *type(); 2393114402Sru int force_tprint(); 2394151497Sru int is_tag(); 2395114402Sru hyphenation_type get_hyphenation_type(); 2396114402Sru}; 2397114402Sru 2398114402Sruhyphen_inhibitor_node::hyphen_inhibitor_node(node *nd) : node(nd) 2399114402Sru{ 2400114402Sru} 2401114402Sru 2402114402Srunode *hyphen_inhibitor_node::copy() 2403114402Sru{ 2404114402Sru return new hyphen_inhibitor_node; 2405114402Sru} 2406114402Sru 2407114402Sruint hyphen_inhibitor_node::same(node *) 2408114402Sru{ 2409114402Sru return 1; 2410114402Sru} 2411114402Sru 2412114402Sruconst char *hyphen_inhibitor_node::type() 2413114402Sru{ 2414114402Sru return "hyphen_inhibitor_node"; 2415114402Sru} 2416114402Sru 2417114402Sruint hyphen_inhibitor_node::force_tprint() 2418114402Sru{ 2419114402Sru return 0; 2420114402Sru} 2421114402Sru 2422151497Sruint hyphen_inhibitor_node::is_tag() 2423151497Sru{ 2424151497Sru return 0; 2425151497Sru} 2426151497Sru 2427114402Sruhyphenation_type hyphen_inhibitor_node::get_hyphenation_type() 2428114402Sru{ 2429114402Sru return HYPHEN_INHIBIT; 2430114402Sru} 2431114402Sru 2432114402Sru/* add_discretionary_hyphen methods */ 2433114402Sru 2434114402Srunode *dbreak_node::add_discretionary_hyphen() 2435114402Sru{ 2436114402Sru if (post) 2437114402Sru post = post->add_discretionary_hyphen(); 2438114402Sru if (none) 2439114402Sru none = none->add_discretionary_hyphen(); 2440114402Sru return this; 2441114402Sru} 2442114402Sru 2443114402Srunode *node::add_discretionary_hyphen() 2444114402Sru{ 2445114402Sru tfont *tf = get_tfont(); 2446114402Sru if (!tf) 2447114402Sru return new hyphen_inhibitor_node(this); 2448114402Sru if (tf->contains(soft_hyphen_char)) { 2449114402Sru color *gcol = get_glyph_color(); 2450114402Sru color *fcol = get_fill_color(); 2451114402Sru node *next1 = next; 2452114402Sru next = 0; 2453114402Sru node *n = copy(); 2454151497Sru glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol, 2455151497Sru state, div_nest_level); 2456114402Sru node *n1 = n->merge_glyph_node(gn); 2457114402Sru if (n1 == 0) { 2458114402Sru gn->next = n; 2459114402Sru n1 = gn; 2460114402Sru } 2461151497Sru return new dbreak_node(this, n1, state, div_nest_level, next1); 2462114402Sru } 2463114402Sru return this; 2464114402Sru} 2465114402Sru 2466114402Srunode *node::merge_self(node *) 2467114402Sru{ 2468114402Sru return 0; 2469114402Sru} 2470114402Sru 2471114402Srunode *node::add_self(node *n, hyphen_list ** /*p*/) 2472114402Sru{ 2473114402Sru next = n; 2474114402Sru return this; 2475114402Sru} 2476114402Sru 2477114402Srunode *kern_pair_node::add_self(node *n, hyphen_list **p) 2478114402Sru{ 2479114402Sru n = n1->add_self(n, p); 2480114402Sru n = n2->add_self(n, p); 2481114402Sru n1 = n2 = 0; 2482114402Sru delete this; 2483114402Sru return n; 2484114402Sru} 2485114402Sru 2486114402Sruhunits node::width() 2487114402Sru{ 2488114402Sru return H0; 2489114402Sru} 2490114402Sru 2491114402Srunode *node::last_char_node() 2492114402Sru{ 2493114402Sru return 0; 2494114402Sru} 2495114402Sru 2496114402Sruint node::force_tprint() 2497114402Sru{ 2498114402Sru return 0; 2499114402Sru} 2500114402Sru 2501151497Sruint node::is_tag() 2502151497Sru{ 2503151497Sru return 0; 2504151497Sru} 2505151497Sru 2506114402Sruhunits hmotion_node::width() 2507114402Sru{ 2508114402Sru return n; 2509114402Sru} 2510114402Sru 2511114402Sruunits node::size() 2512114402Sru{ 2513114402Sru return points_to_units(10); 2514114402Sru} 2515114402Sru 2516151497Sruvoid node::debug_node() 2517151497Sru{ 2518151497Sru fprintf(stderr, "{ %s ", type()); 2519151497Sru if (push_state) 2520151497Sru fprintf(stderr, " <push_state>"); 2521151497Sru if (state) 2522151497Sru fprintf(stderr, " <state>"); 2523151497Sru fprintf(stderr, " nest level %d", div_nest_level); 2524151497Sru fprintf(stderr, " }\n"); 2525151497Sru fflush(stderr); 2526151497Sru} 2527151497Sru 2528151497Sruvoid node::debug_node_list() 2529151497Sru{ 2530151497Sru node *n = next; 2531151497Sru 2532151497Sru debug_node(); 2533151497Sru while (n != 0) { 2534151497Sru n->debug_node(); 2535151497Sru n = n->next; 2536151497Sru } 2537151497Sru} 2538151497Sru 2539114402Sruhunits kern_pair_node::width() 2540114402Sru{ 2541114402Sru return n1->width() + n2->width() + amount; 2542114402Sru} 2543114402Sru 2544114402Srunode *kern_pair_node::last_char_node() 2545114402Sru{ 2546114402Sru node *nd = n2->last_char_node(); 2547114402Sru if (nd) 2548114402Sru return nd; 2549114402Sru return n1->last_char_node(); 2550114402Sru} 2551114402Sru 2552114402Sruhunits dbreak_node::width() 2553114402Sru{ 2554114402Sru hunits x = H0; 2555114402Sru for (node *n = none; n != 0; n = n->next) 2556114402Sru x += n->width(); 2557114402Sru return x; 2558114402Sru} 2559114402Sru 2560114402Srunode *dbreak_node::last_char_node() 2561114402Sru{ 2562114402Sru for (node *n = none; n; n = n->next) { 2563151497Sru node *last_node = n->last_char_node(); 2564151497Sru if (last_node) 2565151497Sru return last_node; 2566114402Sru } 2567114402Sru return 0; 2568114402Sru} 2569114402Sru 2570114402Sruhunits dbreak_node::italic_correction() 2571114402Sru{ 2572114402Sru return none ? none->italic_correction() : H0; 2573114402Sru} 2574114402Sru 2575114402Sruhunits dbreak_node::subscript_correction() 2576114402Sru{ 2577114402Sru return none ? none->subscript_correction() : H0; 2578114402Sru} 2579114402Sru 2580114402Sruclass italic_corrected_node : public node { 2581114402Sru node *n; 2582114402Sru hunits x; 2583114402Srupublic: 2584151497Sru italic_corrected_node(node *, hunits, statem *, int, node * = 0); 2585114402Sru ~italic_corrected_node(); 2586114402Sru node *copy(); 2587114402Sru void ascii_print(ascii_output_file *); 2588114402Sru void asciify(macro *); 2589114402Sru hunits width(); 2590114402Sru node *last_char_node(); 2591114402Sru void vertical_extent(vunits *, vunits *); 2592114402Sru int ends_sentence(); 2593114402Sru int overlaps_horizontally(); 2594114402Sru int overlaps_vertically(); 2595114402Sru int same(node *); 2596114402Sru hyphenation_type get_hyphenation_type(); 2597114402Sru tfont *get_tfont(); 2598114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 2599114402Sru int character_type(); 2600114402Sru void tprint(troff_output_file *); 2601114402Sru hunits subscript_correction(); 2602114402Sru hunits skew(); 2603114402Sru node *add_self(node *, hyphen_list **); 2604114402Sru const char *type(); 2605114402Sru int force_tprint(); 2606151497Sru int is_tag(); 2607114402Sru}; 2608114402Sru 2609151497Srunode *node::add_italic_correction(hunits *wd) 2610114402Sru{ 2611114402Sru hunits ic = italic_correction(); 2612114402Sru if (ic.is_zero()) 2613114402Sru return this; 2614114402Sru else { 2615114402Sru node *next1 = next; 2616114402Sru next = 0; 2617151497Sru *wd += ic; 2618151497Sru return new italic_corrected_node(this, ic, state, div_nest_level, next1); 2619114402Sru } 2620114402Sru} 2621114402Sru 2622151497Sruitalic_corrected_node::italic_corrected_node(node *nn, hunits xx, statem *s, 2623151497Sru int pop, node *p) 2624151497Sru: node(p, s, pop), n(nn), x(xx) 2625114402Sru{ 2626114402Sru assert(n != 0); 2627114402Sru} 2628114402Sru 2629114402Sruitalic_corrected_node::~italic_corrected_node() 2630114402Sru{ 2631114402Sru delete n; 2632114402Sru} 2633114402Sru 2634114402Srunode *italic_corrected_node::copy() 2635114402Sru{ 2636151497Sru return new italic_corrected_node(n->copy(), x, state, div_nest_level); 2637114402Sru} 2638114402Sru 2639114402Sruhunits italic_corrected_node::width() 2640114402Sru{ 2641114402Sru return n->width() + x; 2642114402Sru} 2643114402Sru 2644114402Sruvoid italic_corrected_node::vertical_extent(vunits *min, vunits *max) 2645114402Sru{ 2646114402Sru n->vertical_extent(min, max); 2647114402Sru} 2648114402Sru 2649114402Sruvoid italic_corrected_node::tprint(troff_output_file *out) 2650114402Sru{ 2651114402Sru n->tprint(out); 2652114402Sru out->right(x); 2653114402Sru} 2654114402Sru 2655114402Sruhunits italic_corrected_node::skew() 2656114402Sru{ 2657114402Sru return n->skew() - x/2; 2658114402Sru} 2659114402Sru 2660114402Sruhunits italic_corrected_node::subscript_correction() 2661114402Sru{ 2662114402Sru return n->subscript_correction() - x; 2663114402Sru} 2664114402Sru 2665114402Sruvoid italic_corrected_node::ascii_print(ascii_output_file *out) 2666114402Sru{ 2667114402Sru n->ascii_print(out); 2668114402Sru} 2669114402Sru 2670114402Sruint italic_corrected_node::ends_sentence() 2671114402Sru{ 2672114402Sru return n->ends_sentence(); 2673114402Sru} 2674114402Sru 2675114402Sruint italic_corrected_node::overlaps_horizontally() 2676114402Sru{ 2677114402Sru return n->overlaps_horizontally(); 2678114402Sru} 2679114402Sru 2680114402Sruint italic_corrected_node::overlaps_vertically() 2681114402Sru{ 2682114402Sru return n->overlaps_vertically(); 2683114402Sru} 2684114402Sru 2685114402Srunode *italic_corrected_node::last_char_node() 2686114402Sru{ 2687114402Sru return n->last_char_node(); 2688114402Sru} 2689114402Sru 2690114402Srutfont *italic_corrected_node::get_tfont() 2691114402Sru{ 2692114402Sru return n->get_tfont(); 2693114402Sru} 2694114402Sru 2695114402Sruhyphenation_type italic_corrected_node::get_hyphenation_type() 2696114402Sru{ 2697114402Sru return n->get_hyphenation_type(); 2698114402Sru} 2699114402Sru 2700114402Srunode *italic_corrected_node::add_self(node *nd, hyphen_list **p) 2701114402Sru{ 2702114402Sru nd = n->add_self(nd, p); 2703114402Sru hunits not_interested; 2704114402Sru nd = nd->add_italic_correction(¬_interested); 2705114402Sru n = 0; 2706114402Sru delete this; 2707114402Sru return nd; 2708114402Sru} 2709114402Sru 2710114402Sruhyphen_list *italic_corrected_node::get_hyphen_list(hyphen_list *tail, 2711114402Sru int *count) 2712114402Sru{ 2713114402Sru return n->get_hyphen_list(tail, count); 2714114402Sru} 2715114402Sru 2716114402Sruint italic_corrected_node::character_type() 2717114402Sru{ 2718114402Sru return n->character_type(); 2719114402Sru} 2720114402Sru 2721114402Sruclass break_char_node : public node { 2722114402Sru node *ch; 2723114402Sru char break_code; 2724114402Sru color *col; 2725114402Srupublic: 2726114402Sru break_char_node(node *, int, color *, node * = 0); 2727151497Sru break_char_node(node *, int, color *, statem *, int, node * = 0); 2728114402Sru ~break_char_node(); 2729114402Sru node *copy(); 2730114402Sru hunits width(); 2731114402Sru vunits vertical_width(); 2732114402Sru node *last_char_node(); 2733114402Sru int character_type(); 2734114402Sru int ends_sentence(); 2735114402Sru node *add_self(node *, hyphen_list **); 2736114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 2737114402Sru void tprint(troff_output_file *); 2738114402Sru void zero_width_tprint(troff_output_file *); 2739114402Sru void ascii_print(ascii_output_file *); 2740114402Sru void asciify(macro *); 2741114402Sru hyphenation_type get_hyphenation_type(); 2742114402Sru int overlaps_vertically(); 2743114402Sru int overlaps_horizontally(); 2744114402Sru units size(); 2745114402Sru tfont *get_tfont(); 2746114402Sru int same(node *); 2747114402Sru const char *type(); 2748114402Sru int force_tprint(); 2749151497Sru int is_tag(); 2750114402Sru}; 2751114402Sru 2752114402Srubreak_char_node::break_char_node(node *n, int bc, color *c, node *x) 2753114402Sru: node(x), ch(n), break_code(bc), col(c) 2754114402Sru{ 2755114402Sru} 2756114402Sru 2757151497Srubreak_char_node::break_char_node(node *n, int bc, color *c, statem *s, 2758151497Sru int pop, node *x) 2759151497Sru: node(x, s, pop), ch(n), break_code(bc), col(c) 2760151497Sru{ 2761151497Sru} 2762151497Sru 2763114402Srubreak_char_node::~break_char_node() 2764114402Sru{ 2765114402Sru delete ch; 2766114402Sru} 2767114402Sru 2768114402Srunode *break_char_node::copy() 2769114402Sru{ 2770151497Sru return new break_char_node(ch->copy(), break_code, col, state, 2771151497Sru div_nest_level); 2772114402Sru} 2773114402Sru 2774114402Sruhunits break_char_node::width() 2775114402Sru{ 2776114402Sru return ch->width(); 2777114402Sru} 2778114402Sru 2779114402Sruvunits break_char_node::vertical_width() 2780114402Sru{ 2781114402Sru return ch->vertical_width(); 2782114402Sru} 2783114402Sru 2784114402Srunode *break_char_node::last_char_node() 2785114402Sru{ 2786114402Sru return ch->last_char_node(); 2787114402Sru} 2788114402Sru 2789114402Sruint break_char_node::character_type() 2790114402Sru{ 2791114402Sru return ch->character_type(); 2792114402Sru} 2793114402Sru 2794114402Sruint break_char_node::ends_sentence() 2795114402Sru{ 2796114402Sru return ch->ends_sentence(); 2797114402Sru} 2798114402Sru 2799114402Srunode *break_char_node::add_self(node *n, hyphen_list **p) 2800114402Sru{ 2801114402Sru assert((*p)->hyphenation_code == 0); 2802114402Sru if ((*p)->breakable && (break_code & 1)) { 2803114402Sru n = new space_node(H0, col, n); 2804114402Sru n->freeze_space(); 2805114402Sru } 2806114402Sru next = n; 2807114402Sru n = this; 2808114402Sru if ((*p)->breakable && (break_code & 2)) { 2809114402Sru n = new space_node(H0, col, n); 2810114402Sru n->freeze_space(); 2811114402Sru } 2812114402Sru hyphen_list *pp = *p; 2813114402Sru *p = (*p)->next; 2814114402Sru delete pp; 2815114402Sru return n; 2816114402Sru} 2817114402Sru 2818114402Sruhyphen_list *break_char_node::get_hyphen_list(hyphen_list *tail, int *) 2819114402Sru{ 2820114402Sru return new hyphen_list(0, tail); 2821114402Sru} 2822114402Sru 2823114402Sruhyphenation_type break_char_node::get_hyphenation_type() 2824114402Sru{ 2825114402Sru return HYPHEN_MIDDLE; 2826114402Sru} 2827114402Sru 2828114402Sruvoid break_char_node::ascii_print(ascii_output_file *ascii) 2829114402Sru{ 2830114402Sru ch->ascii_print(ascii); 2831114402Sru} 2832114402Sru 2833114402Sruint break_char_node::overlaps_vertically() 2834114402Sru{ 2835114402Sru return ch->overlaps_vertically(); 2836114402Sru} 2837114402Sru 2838114402Sruint break_char_node::overlaps_horizontally() 2839114402Sru{ 2840114402Sru return ch->overlaps_horizontally(); 2841114402Sru} 2842114402Sru 2843114402Sruunits break_char_node::size() 2844114402Sru{ 2845114402Sru return ch->size(); 2846114402Sru} 2847114402Sru 2848114402Srutfont *break_char_node::get_tfont() 2849114402Sru{ 2850114402Sru return ch->get_tfont(); 2851114402Sru} 2852114402Sru 2853114402Srunode *extra_size_node::copy() 2854114402Sru{ 2855151497Sru return new extra_size_node(n, state, div_nest_level); 2856114402Sru} 2857114402Sru 2858151497Sruextra_size_node::extra_size_node(vunits i, statem *s, int pop) 2859151497Sru: node(0, s, pop), n(i) 2860151497Sru{ 2861151497Sru} 2862151497Sru 2863151497Sruextra_size_node::extra_size_node(vunits i) 2864151497Sru: n(i) 2865151497Sru{ 2866151497Sru} 2867151497Sru 2868114402Srunode *vertical_size_node::copy() 2869114402Sru{ 2870151497Sru return new vertical_size_node(n, state, div_nest_level); 2871114402Sru} 2872114402Sru 2873151497Sruvertical_size_node::vertical_size_node(vunits i, statem *s, int pop) 2874151497Sru: node(0, s, pop), n(i) 2875151497Sru{ 2876151497Sru} 2877151497Sru 2878151497Sruvertical_size_node::vertical_size_node(vunits i) 2879151497Sru: n(i) 2880151497Sru{ 2881151497Sru} 2882151497Sru 2883114402Srunode *hmotion_node::copy() 2884114402Sru{ 2885151497Sru return new hmotion_node(n, was_tab, unformat, col, state, div_nest_level); 2886114402Sru} 2887114402Sru 2888114402Srunode *space_char_hmotion_node::copy() 2889114402Sru{ 2890151497Sru return new space_char_hmotion_node(n, col, state, div_nest_level); 2891114402Sru} 2892114402Sru 2893151497Sruvmotion_node::vmotion_node(vunits i, color *c) 2894151497Sru: n(i), col(c) 2895151497Sru{ 2896151497Sru} 2897151497Sru 2898151497Sruvmotion_node::vmotion_node(vunits i, color *c, statem *s, int pop) 2899151497Sru: node(0, s, pop), n(i), col(c) 2900151497Sru{ 2901151497Sru} 2902151497Sru 2903114402Srunode *vmotion_node::copy() 2904114402Sru{ 2905151497Sru return new vmotion_node(n, col, state, div_nest_level); 2906114402Sru} 2907114402Sru 2908114402Srunode *dummy_node::copy() 2909114402Sru{ 2910114402Sru return new dummy_node; 2911114402Sru} 2912114402Sru 2913114402Srunode *transparent_dummy_node::copy() 2914114402Sru{ 2915114402Sru return new transparent_dummy_node; 2916114402Sru} 2917114402Sru 2918114402Sruhline_node::~hline_node() 2919114402Sru{ 2920114402Sru if (n) 2921114402Sru delete n; 2922114402Sru} 2923114402Sru 2924151497Sruhline_node::hline_node(hunits i, node *c, node *nxt) 2925151497Sru: node(nxt), x(i), n(c) 2926151497Sru{ 2927151497Sru} 2928151497Sru 2929151497Sruhline_node::hline_node(hunits i, node *c, statem *s, int pop, node *nxt) 2930151497Sru: node(nxt, s, pop), x(i), n(c) 2931151497Sru{ 2932151497Sru} 2933151497Sru 2934114402Srunode *hline_node::copy() 2935114402Sru{ 2936151497Sru return new hline_node(x, n ? n->copy() : 0, state, div_nest_level); 2937114402Sru} 2938114402Sru 2939114402Sruhunits hline_node::width() 2940114402Sru{ 2941114402Sru return x < H0 ? H0 : x; 2942114402Sru} 2943114402Sru 2944151497Sruvline_node::vline_node(vunits i, node *c, node *nxt) 2945151497Sru: node(nxt), x(i), n(c) 2946151497Sru{ 2947151497Sru} 2948151497Sru 2949151497Sruvline_node::vline_node(vunits i, node *c, statem *s, int pop, node *nxt) 2950151497Sru: node(nxt, s, pop), x(i), n(c) 2951151497Sru{ 2952151497Sru} 2953151497Sru 2954114402Sruvline_node::~vline_node() 2955114402Sru{ 2956114402Sru if (n) 2957114402Sru delete n; 2958114402Sru} 2959114402Sru 2960114402Srunode *vline_node::copy() 2961114402Sru{ 2962151497Sru return new vline_node(x, n ? n->copy() : 0, state, div_nest_level); 2963114402Sru} 2964114402Sru 2965114402Sruhunits vline_node::width() 2966114402Sru{ 2967114402Sru return n == 0 ? H0 : n->width(); 2968114402Sru} 2969114402Sru 2970151497Sruzero_width_node::zero_width_node(node *nd, statem *s, int pop) 2971151497Sru: node(0, s, pop), n(nd) 2972114402Sru{ 2973114402Sru} 2974114402Sru 2975151497Sruzero_width_node::zero_width_node(node *nd) 2976151497Sru: n(nd) 2977151497Sru{ 2978151497Sru} 2979151497Sru 2980114402Sruzero_width_node::~zero_width_node() 2981114402Sru{ 2982114402Sru delete_node_list(n); 2983114402Sru} 2984114402Sru 2985114402Srunode *zero_width_node::copy() 2986114402Sru{ 2987151497Sru return new zero_width_node(copy_node_list(n), state, div_nest_level); 2988114402Sru} 2989114402Sru 2990114402Sruint node_list_character_type(node *p) 2991114402Sru{ 2992114402Sru int t = 0; 2993114402Sru for (; p; p = p->next) 2994114402Sru t |= p->character_type(); 2995114402Sru return t; 2996114402Sru} 2997114402Sru 2998114402Sruint zero_width_node::character_type() 2999114402Sru{ 3000114402Sru return node_list_character_type(n); 3001114402Sru} 3002114402Sru 3003114402Sruvoid node_list_vertical_extent(node *p, vunits *min, vunits *max) 3004114402Sru{ 3005114402Sru *min = V0; 3006114402Sru *max = V0; 3007114402Sru vunits cur_vpos = V0; 3008114402Sru vunits v1, v2; 3009114402Sru for (; p; p = p->next) { 3010114402Sru p->vertical_extent(&v1, &v2); 3011114402Sru v1 += cur_vpos; 3012114402Sru if (v1 < *min) 3013114402Sru *min = v1; 3014114402Sru v2 += cur_vpos; 3015114402Sru if (v2 > *max) 3016114402Sru *max = v2; 3017114402Sru cur_vpos += p->vertical_width(); 3018114402Sru } 3019114402Sru} 3020114402Sru 3021114402Sruvoid zero_width_node::vertical_extent(vunits *min, vunits *max) 3022114402Sru{ 3023114402Sru node_list_vertical_extent(n, min, max); 3024114402Sru} 3025114402Sru 3026151497Sruoverstrike_node::overstrike_node() 3027151497Sru: list(0), max_width(H0) 3028114402Sru{ 3029114402Sru} 3030114402Sru 3031151497Sruoverstrike_node::overstrike_node(statem *s, int pop) 3032151497Sru: node(0, s, pop), list(0), max_width(H0) 3033151497Sru{ 3034151497Sru} 3035151497Sru 3036114402Sruoverstrike_node::~overstrike_node() 3037114402Sru{ 3038114402Sru delete_node_list(list); 3039114402Sru} 3040114402Sru 3041114402Srunode *overstrike_node::copy() 3042114402Sru{ 3043151497Sru overstrike_node *on = new overstrike_node(state, div_nest_level); 3044114402Sru for (node *tem = list; tem; tem = tem->next) 3045114402Sru on->overstrike(tem->copy()); 3046114402Sru return on; 3047114402Sru} 3048114402Sru 3049114402Sruvoid overstrike_node::overstrike(node *n) 3050114402Sru{ 3051114402Sru if (n == 0) 3052114402Sru return; 3053114402Sru hunits w = n->width(); 3054114402Sru if (w > max_width) 3055114402Sru max_width = w; 3056114402Sru node **p; 3057114402Sru for (p = &list; *p; p = &(*p)->next) 3058114402Sru ; 3059114402Sru n->next = 0; 3060114402Sru *p = n; 3061114402Sru} 3062114402Sru 3063114402Sruhunits overstrike_node::width() 3064114402Sru{ 3065114402Sru return max_width; 3066114402Sru} 3067114402Sru 3068151497Srubracket_node::bracket_node() 3069151497Sru: list(0), max_width(H0) 3070114402Sru{ 3071114402Sru} 3072114402Sru 3073151497Srubracket_node::bracket_node(statem *s, int pop) 3074151497Sru: node(0, s, pop), list(0), max_width(H0) 3075151497Sru{ 3076151497Sru} 3077151497Sru 3078114402Srubracket_node::~bracket_node() 3079114402Sru{ 3080114402Sru delete_node_list(list); 3081114402Sru} 3082114402Sru 3083114402Srunode *bracket_node::copy() 3084114402Sru{ 3085151497Sru bracket_node *on = new bracket_node(state, div_nest_level); 3086151497Sru node *last_node = 0; 3087114402Sru node *tem; 3088114402Sru if (list) 3089114402Sru list->last = 0; 3090114402Sru for (tem = list; tem; tem = tem->next) { 3091114402Sru if (tem->next) 3092114402Sru tem->next->last = tem; 3093151497Sru last_node = tem; 3094114402Sru } 3095151497Sru for (tem = last_node; tem; tem = tem->last) 3096114402Sru on->bracket(tem->copy()); 3097114402Sru return on; 3098114402Sru} 3099114402Sru 3100114402Sruvoid bracket_node::bracket(node *n) 3101114402Sru{ 3102114402Sru if (n == 0) 3103114402Sru return; 3104114402Sru hunits w = n->width(); 3105114402Sru if (w > max_width) 3106114402Sru max_width = w; 3107114402Sru n->next = list; 3108114402Sru list = n; 3109114402Sru} 3110114402Sru 3111114402Sruhunits bracket_node::width() 3112114402Sru{ 3113114402Sru return max_width; 3114114402Sru} 3115114402Sru 3116114402Sruint node::nspaces() 3117114402Sru{ 3118114402Sru return 0; 3119114402Sru} 3120114402Sru 3121114402Sruint node::merge_space(hunits, hunits, hunits) 3122114402Sru{ 3123114402Sru return 0; 3124114402Sru} 3125114402Sru 3126114402Sru#if 0 3127114402Sruspace_node *space_node::free_list = 0; 3128114402Sru 3129114402Sruvoid *space_node::operator new(size_t n) 3130114402Sru{ 3131114402Sru assert(n == sizeof(space_node)); 3132114402Sru if (!free_list) { 3133114402Sru free_list = (space_node *)new char[sizeof(space_node)*BLOCK]; 3134114402Sru for (int i = 0; i < BLOCK - 1; i++) 3135114402Sru free_list[i].next = free_list + i + 1; 3136114402Sru free_list[BLOCK-1].next = 0; 3137114402Sru } 3138114402Sru space_node *p = free_list; 3139114402Sru free_list = (space_node *)(free_list->next); 3140114402Sru p->next = 0; 3141114402Sru return p; 3142114402Sru} 3143114402Sru 3144114402Sruinline void space_node::operator delete(void *p) 3145114402Sru{ 3146114402Sru if (p) { 3147114402Sru ((space_node *)p)->next = free_list; 3148114402Sru free_list = (space_node *)p; 3149114402Sru } 3150114402Sru} 3151114402Sru#endif 3152114402Sru 3153114402Sruspace_node::space_node(hunits nn, color *c, node *p) 3154151497Sru: node(p, 0, 0), n(nn), set(0), was_escape_colon(0), col(c) 3155114402Sru{ 3156114402Sru} 3157114402Sru 3158151497Sruspace_node::space_node(hunits nn, color *c, statem *s, int pop, node *p) 3159151497Sru: node(p, s, pop), n(nn), set(0), was_escape_colon(0), col(c) 3160114402Sru{ 3161114402Sru} 3162114402Sru 3163151497Sruspace_node::space_node(hunits nn, int s, int flag, color *c, statem *st, 3164151497Sru int pop, node *p) 3165151497Sru: node(p, st, pop), n(nn), set(s), was_escape_colon(flag), col(c) 3166151497Sru{ 3167151497Sru} 3168151497Sru 3169114402Sru#if 0 3170114402Sruspace_node::~space_node() 3171114402Sru{ 3172114402Sru} 3173114402Sru#endif 3174114402Sru 3175114402Srunode *space_node::copy() 3176114402Sru{ 3177151497Sru return new space_node(n, set, was_escape_colon, col, state, div_nest_level); 3178114402Sru} 3179114402Sru 3180114402Sruint space_node::force_tprint() 3181114402Sru{ 3182114402Sru return 0; 3183114402Sru} 3184114402Sru 3185151497Sruint space_node::is_tag() 3186151497Sru{ 3187151497Sru return 0; 3188151497Sru} 3189151497Sru 3190114402Sruint space_node::nspaces() 3191114402Sru{ 3192114402Sru return set ? 0 : 1; 3193114402Sru} 3194114402Sru 3195114402Sruint space_node::merge_space(hunits h, hunits, hunits) 3196114402Sru{ 3197114402Sru n += h; 3198114402Sru return 1; 3199114402Sru} 3200114402Sru 3201114402Sruhunits space_node::width() 3202114402Sru{ 3203114402Sru return n; 3204114402Sru} 3205114402Sru 3206114402Sruvoid node::spread_space(int*, hunits*) 3207114402Sru{ 3208114402Sru} 3209114402Sru 3210151497Sruvoid space_node::spread_space(int *n_spaces, hunits *desired_space) 3211114402Sru{ 3212114402Sru if (!set) { 3213151497Sru assert(*n_spaces > 0); 3214151497Sru if (*n_spaces == 1) { 3215114402Sru n += *desired_space; 3216114402Sru *desired_space = H0; 3217114402Sru } 3218114402Sru else { 3219151497Sru hunits extra = *desired_space / *n_spaces; 3220114402Sru *desired_space -= extra; 3221114402Sru n += extra; 3222114402Sru } 3223151497Sru *n_spaces -= 1; 3224114402Sru set = 1; 3225114402Sru } 3226114402Sru} 3227114402Sru 3228114402Sruvoid node::freeze_space() 3229114402Sru{ 3230114402Sru} 3231114402Sru 3232114402Sruvoid space_node::freeze_space() 3233114402Sru{ 3234114402Sru set = 1; 3235114402Sru} 3236114402Sru 3237114402Sruvoid node::is_escape_colon() 3238114402Sru{ 3239114402Sru} 3240114402Sru 3241114402Sruvoid space_node::is_escape_colon() 3242114402Sru{ 3243114402Sru was_escape_colon = 1; 3244114402Sru} 3245114402Sru 3246151497Srudiverted_space_node::diverted_space_node(vunits d, statem *s, int pop, 3247151497Sru node *p) 3248151497Sru: node(p, s, pop), n(d) 3249151497Sru{ 3250151497Sru} 3251151497Sru 3252114402Srudiverted_space_node::diverted_space_node(vunits d, node *p) 3253114402Sru: node(p), n(d) 3254114402Sru{ 3255114402Sru} 3256114402Sru 3257114402Srunode *diverted_space_node::copy() 3258114402Sru{ 3259151497Sru return new diverted_space_node(n, state, div_nest_level); 3260114402Sru} 3261114402Sru 3262151497Srudiverted_copy_file_node::diverted_copy_file_node(symbol s, statem *st, 3263151497Sru int pop, node *p) 3264151497Sru: node(p, st, pop), filename(s) 3265151497Sru{ 3266151497Sru} 3267151497Sru 3268114402Srudiverted_copy_file_node::diverted_copy_file_node(symbol s, node *p) 3269114402Sru: node(p), filename(s) 3270114402Sru{ 3271114402Sru} 3272114402Sru 3273114402Srunode *diverted_copy_file_node::copy() 3274114402Sru{ 3275151497Sru return new diverted_copy_file_node(filename, state, div_nest_level); 3276114402Sru} 3277114402Sru 3278114402Sruint node::ends_sentence() 3279114402Sru{ 3280114402Sru return 0; 3281114402Sru} 3282114402Sru 3283114402Sruint kern_pair_node::ends_sentence() 3284114402Sru{ 3285114402Sru switch (n2->ends_sentence()) { 3286114402Sru case 0: 3287114402Sru return 0; 3288114402Sru case 1: 3289114402Sru return 1; 3290114402Sru case 2: 3291114402Sru break; 3292114402Sru default: 3293114402Sru assert(0); 3294114402Sru } 3295114402Sru return n1->ends_sentence(); 3296114402Sru} 3297114402Sru 3298114402Sruint node_list_ends_sentence(node *n) 3299114402Sru{ 3300114402Sru for (; n != 0; n = n->next) 3301114402Sru switch (n->ends_sentence()) { 3302114402Sru case 0: 3303114402Sru return 0; 3304114402Sru case 1: 3305114402Sru return 1; 3306114402Sru case 2: 3307114402Sru break; 3308114402Sru default: 3309114402Sru assert(0); 3310114402Sru } 3311114402Sru return 2; 3312114402Sru} 3313114402Sru 3314114402Sruint dbreak_node::ends_sentence() 3315114402Sru{ 3316114402Sru return node_list_ends_sentence(none); 3317114402Sru} 3318114402Sru 3319114402Sruint node::overlaps_horizontally() 3320114402Sru{ 3321114402Sru return 0; 3322114402Sru} 3323114402Sru 3324114402Sruint node::overlaps_vertically() 3325114402Sru{ 3326114402Sru return 0; 3327114402Sru} 3328114402Sru 3329114402Sruint node::discardable() 3330114402Sru{ 3331114402Sru return 0; 3332114402Sru} 3333114402Sru 3334114402Sruint space_node::discardable() 3335114402Sru{ 3336114402Sru return set ? 0 : 1; 3337114402Sru} 3338114402Sru 3339114402Sruvunits node::vertical_width() 3340114402Sru{ 3341114402Sru return V0; 3342114402Sru} 3343114402Sru 3344114402Sruvunits vline_node::vertical_width() 3345114402Sru{ 3346114402Sru return x; 3347114402Sru} 3348114402Sru 3349114402Sruvunits vmotion_node::vertical_width() 3350114402Sru{ 3351114402Sru return n; 3352114402Sru} 3353114402Sru 3354114402Sruint node::set_unformat_flag() 3355114402Sru{ 3356114402Sru return 1; 3357114402Sru} 3358114402Sru 3359114402Sruint node::character_type() 3360114402Sru{ 3361114402Sru return 0; 3362114402Sru} 3363114402Sru 3364114402Sruhunits node::subscript_correction() 3365114402Sru{ 3366114402Sru return H0; 3367114402Sru} 3368114402Sru 3369114402Sruhunits node::italic_correction() 3370114402Sru{ 3371114402Sru return H0; 3372114402Sru} 3373114402Sru 3374114402Sruhunits node::left_italic_correction() 3375114402Sru{ 3376114402Sru return H0; 3377114402Sru} 3378114402Sru 3379114402Sruhunits node::skew() 3380114402Sru{ 3381114402Sru return H0; 3382114402Sru} 3383114402Sru 3384114402Sru/* vertical_extent methods */ 3385114402Sru 3386114402Sruvoid node::vertical_extent(vunits *min, vunits *max) 3387114402Sru{ 3388114402Sru vunits v = vertical_width(); 3389114402Sru if (v < V0) { 3390114402Sru *min = v; 3391114402Sru *max = V0; 3392114402Sru } 3393114402Sru else { 3394114402Sru *max = v; 3395114402Sru *min = V0; 3396114402Sru } 3397114402Sru} 3398114402Sru 3399114402Sruvoid vline_node::vertical_extent(vunits *min, vunits *max) 3400114402Sru{ 3401114402Sru if (n == 0) 3402114402Sru node::vertical_extent(min, max); 3403114402Sru else { 3404114402Sru vunits cmin, cmax; 3405114402Sru n->vertical_extent(&cmin, &cmax); 3406114402Sru vunits h = n->size(); 3407114402Sru if (x < V0) { 3408114402Sru if (-x < h) { 3409114402Sru *min = x; 3410114402Sru *max = V0; 3411114402Sru } 3412114402Sru else { 3413114402Sru // we print the first character and then move up, so 3414114402Sru *max = cmax; 3415114402Sru // we print the last character and then move up h 3416114402Sru *min = cmin + h; 3417114402Sru if (*min > V0) 3418114402Sru *min = V0; 3419114402Sru *min += x; 3420114402Sru } 3421114402Sru } 3422114402Sru else { 3423114402Sru if (x < h) { 3424114402Sru *max = x; 3425114402Sru *min = V0; 3426114402Sru } 3427114402Sru else { 3428114402Sru // we move down by h and then print the first character, so 3429114402Sru *min = cmin + h; 3430114402Sru if (*min > V0) 3431114402Sru *min = V0; 3432114402Sru *max = x + cmax; 3433114402Sru } 3434114402Sru } 3435114402Sru } 3436114402Sru} 3437114402Sru 3438114402Sru/* ascii_print methods */ 3439114402Sru 3440114402Srustatic void ascii_print_reverse_node_list(ascii_output_file *ascii, node *n) 3441114402Sru{ 3442114402Sru if (n == 0) 3443114402Sru return; 3444114402Sru ascii_print_reverse_node_list(ascii, n->next); 3445114402Sru n->ascii_print(ascii); 3446114402Sru} 3447114402Sru 3448114402Sruvoid dbreak_node::ascii_print(ascii_output_file *ascii) 3449114402Sru{ 3450114402Sru ascii_print_reverse_node_list(ascii, none); 3451114402Sru} 3452114402Sru 3453114402Sruvoid kern_pair_node::ascii_print(ascii_output_file *ascii) 3454114402Sru{ 3455114402Sru n1->ascii_print(ascii); 3456114402Sru n2->ascii_print(ascii); 3457114402Sru} 3458114402Sru 3459114402Sruvoid node::ascii_print(ascii_output_file *) 3460114402Sru{ 3461114402Sru} 3462114402Sru 3463114402Sruvoid space_node::ascii_print(ascii_output_file *ascii) 3464114402Sru{ 3465114402Sru if (!n.is_zero()) 3466114402Sru ascii->outc(' '); 3467114402Sru} 3468114402Sru 3469114402Sruvoid hmotion_node::ascii_print(ascii_output_file *ascii) 3470114402Sru{ 3471114402Sru // this is pretty arbitrary 3472114402Sru if (n >= points_to_units(2)) 3473114402Sru ascii->outc(' '); 3474114402Sru} 3475114402Sru 3476114402Sruvoid space_char_hmotion_node::ascii_print(ascii_output_file *ascii) 3477114402Sru{ 3478114402Sru ascii->outc(' '); 3479114402Sru} 3480114402Sru 3481114402Sru/* asciify methods */ 3482114402Sru 3483114402Sruvoid node::asciify(macro *m) 3484114402Sru{ 3485114402Sru m->append(this); 3486114402Sru} 3487114402Sru 3488114402Sruvoid glyph_node::asciify(macro *m) 3489114402Sru{ 3490114402Sru unsigned char c = ci->get_asciify_code(); 3491114402Sru if (c == 0) 3492114402Sru c = ci->get_ascii_code(); 3493114402Sru if (c != 0) { 3494114402Sru m->append(c); 3495114402Sru delete this; 3496114402Sru } 3497114402Sru else 3498114402Sru m->append(this); 3499114402Sru} 3500114402Sru 3501114402Sruvoid kern_pair_node::asciify(macro *m) 3502114402Sru{ 3503114402Sru n1->asciify(m); 3504114402Sru n2->asciify(m); 3505114402Sru n1 = n2 = 0; 3506114402Sru delete this; 3507114402Sru} 3508114402Sru 3509114402Srustatic void asciify_reverse_node_list(macro *m, node *n) 3510114402Sru{ 3511114402Sru if (n == 0) 3512114402Sru return; 3513114402Sru asciify_reverse_node_list(m, n->next); 3514114402Sru n->asciify(m); 3515114402Sru} 3516114402Sru 3517114402Sruvoid dbreak_node::asciify(macro *m) 3518114402Sru{ 3519114402Sru asciify_reverse_node_list(m, none); 3520114402Sru none = 0; 3521114402Sru delete this; 3522114402Sru} 3523114402Sru 3524114402Sruvoid ligature_node::asciify(macro *m) 3525114402Sru{ 3526114402Sru n1->asciify(m); 3527114402Sru n2->asciify(m); 3528114402Sru n1 = n2 = 0; 3529114402Sru delete this; 3530114402Sru} 3531114402Sru 3532114402Sruvoid break_char_node::asciify(macro *m) 3533114402Sru{ 3534114402Sru ch->asciify(m); 3535114402Sru ch = 0; 3536114402Sru delete this; 3537114402Sru} 3538114402Sru 3539114402Sruvoid italic_corrected_node::asciify(macro *m) 3540114402Sru{ 3541114402Sru n->asciify(m); 3542114402Sru n = 0; 3543114402Sru delete this; 3544114402Sru} 3545114402Sru 3546114402Sruvoid left_italic_corrected_node::asciify(macro *m) 3547114402Sru{ 3548114402Sru if (n) { 3549114402Sru n->asciify(m); 3550114402Sru n = 0; 3551114402Sru } 3552114402Sru delete this; 3553114402Sru} 3554114402Sru 3555114402Sruvoid hmotion_node::asciify(macro *m) 3556114402Sru{ 3557114402Sru if (was_tab) { 3558114402Sru m->append('\t'); 3559114402Sru delete this; 3560114402Sru } 3561114402Sru else 3562114402Sru m->append(this); 3563114402Sru} 3564114402Sru 3565114402Sruspace_char_hmotion_node::space_char_hmotion_node(hunits i, color *c, 3566151497Sru statem *s, int pop, 3567151497Sru node *nxt) 3568151497Sru: hmotion_node(i, c, s, pop, nxt) 3569114402Sru{ 3570114402Sru} 3571114402Sru 3572151497Sruspace_char_hmotion_node::space_char_hmotion_node(hunits i, color *c, 3573151497Sru node *nxt) 3574151497Sru: hmotion_node(i, c, 0, 0, nxt) 3575151497Sru{ 3576151497Sru} 3577151497Sru 3578114402Sruvoid space_char_hmotion_node::asciify(macro *m) 3579114402Sru{ 3580114402Sru m->append(ESCAPE_SPACE); 3581114402Sru delete this; 3582114402Sru} 3583114402Sru 3584114402Sruvoid space_node::asciify(macro *m) 3585114402Sru{ 3586114402Sru if (was_escape_colon) { 3587114402Sru m->append(ESCAPE_COLON); 3588114402Sru delete this; 3589114402Sru } 3590114402Sru else 3591114402Sru m->append(this); 3592114402Sru} 3593114402Sru 3594114402Sruvoid word_space_node::asciify(macro *m) 3595114402Sru{ 3596114402Sru for (width_list *w = orig_width; w; w = w->next) 3597114402Sru m->append(' '); 3598114402Sru delete this; 3599114402Sru} 3600114402Sru 3601114402Sruvoid unbreakable_space_node::asciify(macro *m) 3602114402Sru{ 3603114402Sru m->append(ESCAPE_TILDE); 3604114402Sru delete this; 3605114402Sru} 3606114402Sru 3607114402Sruvoid line_start_node::asciify(macro *) 3608114402Sru{ 3609114402Sru delete this; 3610114402Sru} 3611114402Sru 3612114402Sruvoid vertical_size_node::asciify(macro *) 3613114402Sru{ 3614114402Sru delete this; 3615114402Sru} 3616114402Sru 3617114402Srubreakpoint *node::get_breakpoints(hunits /*width*/, int /*nspaces*/, 3618114402Sru breakpoint *rest, int /*is_inner*/) 3619114402Sru{ 3620114402Sru return rest; 3621114402Sru} 3622114402Sru 3623114402Sruint node::nbreaks() 3624114402Sru{ 3625114402Sru return 0; 3626114402Sru} 3627114402Sru 3628151497Srubreakpoint *space_node::get_breakpoints(hunits wd, int ns, 3629114402Sru breakpoint *rest, int is_inner) 3630114402Sru{ 3631151497Sru if (next && next->discardable()) 3632114402Sru return rest; 3633114402Sru breakpoint *bp = new breakpoint; 3634114402Sru bp->next = rest; 3635151497Sru bp->width = wd; 3636114402Sru bp->nspaces = ns; 3637114402Sru bp->hyphenated = 0; 3638114402Sru if (is_inner) { 3639114402Sru assert(rest != 0); 3640114402Sru bp->index = rest->index + 1; 3641114402Sru bp->nd = rest->nd; 3642114402Sru } 3643114402Sru else { 3644114402Sru bp->nd = this; 3645114402Sru bp->index = 0; 3646114402Sru } 3647114402Sru return bp; 3648114402Sru} 3649114402Sru 3650114402Sruint space_node::nbreaks() 3651114402Sru{ 3652151497Sru if (next && next->discardable()) 3653114402Sru return 0; 3654114402Sru else 3655114402Sru return 1; 3656114402Sru} 3657114402Sru 3658114402Srustatic breakpoint *node_list_get_breakpoints(node *p, hunits *widthp, 3659114402Sru int ns, breakpoint *rest) 3660114402Sru{ 3661114402Sru if (p != 0) { 3662114402Sru rest = p->get_breakpoints(*widthp, 3663114402Sru ns, 3664114402Sru node_list_get_breakpoints(p->next, widthp, ns, 3665114402Sru rest), 3666114402Sru 1); 3667114402Sru *widthp += p->width(); 3668114402Sru } 3669114402Sru return rest; 3670114402Sru} 3671114402Sru 3672151497Srubreakpoint *dbreak_node::get_breakpoints(hunits wd, int ns, 3673114402Sru breakpoint *rest, int is_inner) 3674114402Sru{ 3675114402Sru breakpoint *bp = new breakpoint; 3676114402Sru bp->next = rest; 3677151497Sru bp->width = wd; 3678114402Sru for (node *tem = pre; tem != 0; tem = tem->next) 3679114402Sru bp->width += tem->width(); 3680114402Sru bp->nspaces = ns; 3681114402Sru bp->hyphenated = 1; 3682114402Sru if (is_inner) { 3683114402Sru assert(rest != 0); 3684114402Sru bp->index = rest->index + 1; 3685114402Sru bp->nd = rest->nd; 3686114402Sru } 3687114402Sru else { 3688114402Sru bp->nd = this; 3689114402Sru bp->index = 0; 3690114402Sru } 3691151497Sru return node_list_get_breakpoints(none, &wd, ns, bp); 3692114402Sru} 3693114402Sru 3694114402Sruint dbreak_node::nbreaks() 3695114402Sru{ 3696114402Sru int i = 1; 3697114402Sru for (node *tem = none; tem != 0; tem = tem->next) 3698114402Sru i += tem->nbreaks(); 3699114402Sru return i; 3700114402Sru} 3701114402Sru 3702114402Sruvoid node::split(int /*where*/, node ** /*prep*/, node ** /*postp*/) 3703114402Sru{ 3704114402Sru assert(0); 3705114402Sru} 3706114402Sru 3707114402Sruvoid space_node::split(int where, node **pre, node **post) 3708114402Sru{ 3709114402Sru assert(where == 0); 3710114402Sru *pre = next; 3711114402Sru *post = 0; 3712114402Sru delete this; 3713114402Sru} 3714114402Sru 3715114402Srustatic void node_list_split(node *p, int *wherep, node **prep, node **postp) 3716114402Sru{ 3717114402Sru if (p == 0) 3718114402Sru return; 3719114402Sru int nb = p->nbreaks(); 3720114402Sru node_list_split(p->next, wherep, prep, postp); 3721114402Sru if (*wherep < 0) { 3722114402Sru p->next = *postp; 3723114402Sru *postp = p; 3724114402Sru } 3725114402Sru else if (*wherep < nb) { 3726114402Sru p->next = *prep; 3727114402Sru p->split(*wherep, prep, postp); 3728114402Sru } 3729114402Sru else { 3730114402Sru p->next = *prep; 3731114402Sru *prep = p; 3732114402Sru } 3733114402Sru *wherep -= nb; 3734114402Sru} 3735114402Sru 3736114402Sruvoid dbreak_node::split(int where, node **prep, node **postp) 3737114402Sru{ 3738114402Sru assert(where >= 0); 3739114402Sru if (where == 0) { 3740114402Sru *postp = post; 3741114402Sru post = 0; 3742114402Sru if (pre == 0) 3743114402Sru *prep = next; 3744114402Sru else { 3745114402Sru node *tem; 3746114402Sru for (tem = pre; tem->next != 0; tem = tem->next) 3747114402Sru ; 3748114402Sru tem->next = next; 3749114402Sru *prep = pre; 3750114402Sru } 3751114402Sru pre = 0; 3752114402Sru delete this; 3753114402Sru } 3754114402Sru else { 3755114402Sru *prep = next; 3756114402Sru where -= 1; 3757114402Sru node_list_split(none, &where, prep, postp); 3758114402Sru none = 0; 3759114402Sru delete this; 3760114402Sru } 3761114402Sru} 3762114402Sru 3763114402Sruhyphenation_type node::get_hyphenation_type() 3764114402Sru{ 3765114402Sru return HYPHEN_BOUNDARY; 3766114402Sru} 3767114402Sru 3768114402Sruhyphenation_type dbreak_node::get_hyphenation_type() 3769114402Sru{ 3770114402Sru return HYPHEN_INHIBIT; 3771114402Sru} 3772114402Sru 3773114402Sruhyphenation_type kern_pair_node::get_hyphenation_type() 3774114402Sru{ 3775114402Sru return HYPHEN_MIDDLE; 3776114402Sru} 3777114402Sru 3778114402Sruhyphenation_type dummy_node::get_hyphenation_type() 3779114402Sru{ 3780114402Sru return HYPHEN_MIDDLE; 3781114402Sru} 3782114402Sru 3783114402Sruhyphenation_type transparent_dummy_node::get_hyphenation_type() 3784114402Sru{ 3785114402Sru return HYPHEN_MIDDLE; 3786114402Sru} 3787114402Sru 3788114402Sruhyphenation_type hmotion_node::get_hyphenation_type() 3789114402Sru{ 3790114402Sru return HYPHEN_MIDDLE; 3791114402Sru} 3792114402Sru 3793114402Sruhyphenation_type space_char_hmotion_node::get_hyphenation_type() 3794114402Sru{ 3795114402Sru return HYPHEN_MIDDLE; 3796114402Sru} 3797114402Sru 3798114402Sruhyphenation_type overstrike_node::get_hyphenation_type() 3799114402Sru{ 3800114402Sru return HYPHEN_MIDDLE; 3801114402Sru} 3802114402Sru 3803114402Sruhyphenation_type space_node::get_hyphenation_type() 3804114402Sru{ 3805114402Sru if (was_escape_colon) 3806114402Sru return HYPHEN_MIDDLE; 3807114402Sru return HYPHEN_BOUNDARY; 3808114402Sru} 3809114402Sru 3810114402Sruhyphenation_type unbreakable_space_node::get_hyphenation_type() 3811114402Sru{ 3812114402Sru return HYPHEN_MIDDLE; 3813114402Sru} 3814114402Sru 3815114402Sruint node::interpret(macro *) 3816114402Sru{ 3817114402Sru return 0; 3818114402Sru} 3819114402Sru 3820114402Sruspecial_node::special_node(const macro &m, int n) 3821114402Sru: mac(m), no_init_string(n) 3822114402Sru{ 3823114402Sru font_size fs = curenv->get_font_size(); 3824114402Sru int char_height = curenv->get_char_height(); 3825114402Sru int char_slant = curenv->get_char_slant(); 3826114402Sru int fontno = env_definite_font(curenv); 3827114402Sru tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fontno); 3828114402Sru if (curenv->is_composite()) 3829114402Sru tf = tf->get_plain(); 3830114402Sru gcol = curenv->get_glyph_color(); 3831114402Sru fcol = curenv->get_fill_color(); 3832151497Sru is_special = 1; 3833114402Sru} 3834114402Sru 3835114402Sruspecial_node::special_node(const macro &m, tfont *t, 3836151497Sru color *gc, color *fc, 3837151497Sru statem *s, int pop, 3838151497Sru int n) 3839151497Sru: node(0, s, pop), mac(m), tf(t), gcol(gc), fcol(fc), no_init_string(n) 3840114402Sru{ 3841151497Sru is_special = 1; 3842114402Sru} 3843114402Sru 3844114402Sruint special_node::same(node *n) 3845114402Sru{ 3846114402Sru return mac == ((special_node *)n)->mac 3847114402Sru && tf == ((special_node *)n)->tf 3848114402Sru && gcol == ((special_node *)n)->gcol 3849114402Sru && fcol == ((special_node *)n)->fcol 3850114402Sru && no_init_string == ((special_node *)n)->no_init_string; 3851114402Sru} 3852114402Sru 3853114402Sruconst char *special_node::type() 3854114402Sru{ 3855114402Sru return "special_node"; 3856114402Sru} 3857114402Sru 3858114402Sruint special_node::ends_sentence() 3859114402Sru{ 3860114402Sru return 2; 3861114402Sru} 3862114402Sru 3863114402Sruint special_node::force_tprint() 3864114402Sru{ 3865114402Sru return 0; 3866114402Sru} 3867114402Sru 3868151497Sruint special_node::is_tag() 3869151497Sru{ 3870151497Sru return 0; 3871151497Sru} 3872151497Sru 3873114402Srunode *special_node::copy() 3874114402Sru{ 3875151497Sru return new special_node(mac, tf, gcol, fcol, state, div_nest_level, 3876151497Sru no_init_string); 3877114402Sru} 3878114402Sru 3879114402Sruvoid special_node::tprint_start(troff_output_file *out) 3880114402Sru{ 3881114402Sru out->start_special(tf, gcol, fcol, no_init_string); 3882114402Sru} 3883114402Sru 3884114402Sruvoid special_node::tprint_char(troff_output_file *out, unsigned char c) 3885114402Sru{ 3886114402Sru out->special_char(c); 3887114402Sru} 3888114402Sru 3889114402Sruvoid special_node::tprint_end(troff_output_file *out) 3890114402Sru{ 3891114402Sru out->end_special(); 3892114402Sru} 3893114402Sru 3894114402Srutfont *special_node::get_tfont() 3895114402Sru{ 3896114402Sru return tf; 3897114402Sru} 3898114402Sru 3899114402Sru/* suppress_node */ 3900114402Sru 3901114402Srusuppress_node::suppress_node(int on_or_off, int issue_limits) 3902151497Sru: is_on(on_or_off), emit_limits(issue_limits), filename(0), position(0), 3903151497Sru image_id(0) 3904114402Sru{ 3905114402Sru} 3906114402Sru 3907114402Srusuppress_node::suppress_node(symbol f, char p, int id) 3908114402Sru: is_on(2), emit_limits(0), filename(f), position(p), image_id(id) 3909114402Sru{ 3910151497Sru is_special = 1; 3911114402Sru} 3912114402Sru 3913114402Srusuppress_node::suppress_node(int issue_limits, int on_or_off, 3914151497Sru symbol f, char p, int id, 3915151497Sru statem *s, int pop) 3916151497Sru: node(0, s, pop), is_on(on_or_off), emit_limits(issue_limits), filename(f), 3917151497Sru position(p), image_id(id) 3918114402Sru{ 3919114402Sru} 3920114402Sru 3921114402Sruint suppress_node::same(node *n) 3922114402Sru{ 3923114402Sru return ((is_on == ((suppress_node *)n)->is_on) 3924114402Sru && (emit_limits == ((suppress_node *)n)->emit_limits) 3925114402Sru && (filename == ((suppress_node *)n)->filename) 3926114402Sru && (position == ((suppress_node *)n)->position) 3927114402Sru && (image_id == ((suppress_node *)n)->image_id)); 3928114402Sru} 3929114402Sru 3930114402Sruconst char *suppress_node::type() 3931114402Sru{ 3932114402Sru return "suppress_node"; 3933114402Sru} 3934114402Sru 3935114402Srunode *suppress_node::copy() 3936114402Sru{ 3937151497Sru return new suppress_node(emit_limits, is_on, filename, position, image_id, 3938151497Sru state, div_nest_level); 3939114402Sru} 3940114402Sru 3941151497Sru/* tag_node */ 3942151497Sru 3943151497Srutag_node::tag_node() 3944151497Sru: delayed(0) 3945151497Sru{ 3946151497Sru is_special = 1; 3947151497Sru} 3948151497Sru 3949151497Srutag_node::tag_node(string s, int delay) 3950151497Sru: tag_string(s), delayed(delay) 3951151497Sru{ 3952151497Sru is_special = !delay; 3953151497Sru} 3954151497Sru 3955151497Srutag_node::tag_node(string s, statem *st, int pop, int delay) 3956151497Sru: node(0, st, pop), tag_string(s), delayed(delay) 3957151497Sru{ 3958151497Sru is_special = !delay; 3959151497Sru} 3960151497Sru 3961151497Srunode *tag_node::copy() 3962151497Sru{ 3963151497Sru return new tag_node(tag_string, state, div_nest_level, delayed); 3964151497Sru} 3965151497Sru 3966151497Sruvoid tag_node::tprint(troff_output_file *out) 3967151497Sru{ 3968151497Sru if (delayed) 3969151497Sru out->add_to_tag_list(tag_string); 3970151497Sru else 3971151497Sru out->state.add_tag(out->fp, tag_string); 3972151497Sru} 3973151497Sru 3974151497Sruint tag_node::same(node *nd) 3975151497Sru{ 3976151497Sru return tag_string == ((tag_node *)nd)->tag_string 3977151497Sru && delayed == ((tag_node *)nd)->delayed; 3978151497Sru} 3979151497Sru 3980151497Sruconst char *tag_node::type() 3981151497Sru{ 3982151497Sru return "tag_node"; 3983151497Sru} 3984151497Sru 3985151497Sruint tag_node::force_tprint() 3986151497Sru{ 3987151497Sru return !delayed; 3988151497Sru} 3989151497Sru 3990151497Sruint tag_node::is_tag() 3991151497Sru{ 3992151497Sru return !delayed; 3993151497Sru} 3994151497Sru 3995151497Sruint tag_node::ends_sentence() 3996151497Sru{ 3997151497Sru return 2; 3998151497Sru} 3999151497Sru 4000114402Sruint get_reg_int(const char *p) 4001114402Sru{ 4002114402Sru reg *r = (reg *)number_reg_dictionary.lookup(p); 4003114402Sru units prev_value; 4004114402Sru if (r && (r->get_value(&prev_value))) 4005114402Sru return (int)prev_value; 4006114402Sru else 4007114402Sru warning(WARN_REG, "number register `%1' not defined", p); 4008114402Sru return 0; 4009114402Sru} 4010114402Sru 4011114402Sruconst char *get_reg_str(const char *p) 4012114402Sru{ 4013114402Sru reg *r = (reg *)number_reg_dictionary.lookup(p); 4014114402Sru if (r) 4015114402Sru return r->get_string(); 4016114402Sru else 4017114402Sru warning(WARN_REG, "register `%1' not defined", p); 4018114402Sru return 0; 4019114402Sru} 4020114402Sru 4021114402Sruvoid suppress_node::put(troff_output_file *out, const char *s) 4022114402Sru{ 4023114402Sru int i = 0; 4024114402Sru while (s[i] != (char)0) { 4025114402Sru out->special_char(s[i]); 4026114402Sru i++; 4027114402Sru } 4028114402Sru} 4029114402Sru 4030114402Sru/* 4031114402Sru * We need to remember the start of the image and its name. 4032114402Sru */ 4033114402Sru 4034114402Srustatic char last_position = 0; 4035114402Srustatic const char *last_image_filename = 0; 4036114402Srustatic int last_image_id = 0; 4037114402Sru 4038114402Sruinline int min(int a, int b) 4039114402Sru{ 4040114402Sru return a < b ? a : b; 4041114402Sru} 4042114402Sru 4043114402Sru/* 4044114402Sru * tprint - if (is_on == 2) 4045114402Sru * remember current position (l, r, c, i) and filename 4046114402Sru * else 4047114402Sru * if (emit_limits) 4048114402Sru * if (html) 4049114402Sru * emit image tag 4050114402Sru * else 4051114402Sru * emit postscript bounds for image 4052114402Sru * else 4053114402Sru * if (suppress boolean differs from current state) 4054114402Sru * alter state 4055114402Sru * reset registers 4056114402Sru * record current page 4057114402Sru * set low water mark. 4058114402Sru */ 4059114402Sru 4060114402Sruvoid suppress_node::tprint(troff_output_file *out) 4061114402Sru{ 4062114402Sru int current_page = topdiv->get_page_number(); 4063114402Sru // firstly check to see whether this suppress node contains 4064114402Sru // an image filename & position. 4065114402Sru if (is_on == 2) { 4066114402Sru // remember position and filename 4067114402Sru last_position = position; 4068151497Sru char *tem = (char *)last_image_filename; 4069114402Sru last_image_filename = strsave(filename.contents()); 4070114402Sru if (tem) 4071151497Sru a_delete tem; 4072114402Sru last_image_id = image_id; 4073114402Sru // printf("start of image and page = %d\n", current_page); 4074114402Sru } 4075114402Sru else { 4076114402Sru // now check whether the suppress node requires us to issue limits. 4077114402Sru if (emit_limits) { 4078114402Sru char name[8192]; 4079114402Sru // remember that the filename will contain a %d in which the 4080114402Sru // last_image_id is placed 4081151497Sru if (last_image_filename == (char *) 0) 4082151497Sru *name = '\0'; 4083151497Sru else 4084151497Sru sprintf(name, last_image_filename, last_image_id); 4085114402Sru if (is_html) { 4086114402Sru switch (last_position) { 4087114402Sru case 'c': 4088114402Sru out->start_special(); 4089151497Sru put(out, "devtag:.centered-image"); 4090114402Sru break; 4091114402Sru case 'r': 4092114402Sru out->start_special(); 4093151497Sru put(out, "devtag:.right-image"); 4094114402Sru break; 4095114402Sru case 'l': 4096114402Sru out->start_special(); 4097151497Sru put(out, "devtag:.left-image"); 4098114402Sru break; 4099114402Sru case 'i': 4100114402Sru ; 4101114402Sru default: 4102114402Sru ; 4103114402Sru } 4104114402Sru out->end_special(); 4105114402Sru out->start_special(); 4106151497Sru put(out, "devtag:.auto-image "); 4107114402Sru put(out, name); 4108114402Sru out->end_special(); 4109114402Sru } 4110114402Sru else { 4111114402Sru // postscript (or other device) 4112114402Sru if (suppress_start_page > 0 && current_page != suppress_start_page) 4113114402Sru error("suppression limit registers span more than one page;\n" 4114114402Sru "image description %1 will be wrong", image_no); 4115114402Sru // if (topdiv->get_page_number() != suppress_start_page) 4116114402Sru // fprintf(stderr, "end of image and topdiv page = %d and suppress_start_page = %d\n", 4117114402Sru // topdiv->get_page_number(), suppress_start_page); 4118114402Sru 4119114402Sru // remember that the filename will contain a %d in which the 4120114402Sru // image_no is placed 4121114402Sru fprintf(stderr, 4122114402Sru "grohtml-info:page %d %d %d %d %d %d %s %d %d %s\n", 4123114402Sru topdiv->get_page_number(), 4124114402Sru get_reg_int("opminx"), get_reg_int("opminy"), 4125114402Sru get_reg_int("opmaxx"), get_reg_int("opmaxy"), 4126114402Sru // page offset + line length 4127114402Sru get_reg_int(".o") + get_reg_int(".l"), 4128114402Sru name, hresolution, vresolution, get_reg_str(".F")); 4129114402Sru fflush(stderr); 4130114402Sru } 4131114402Sru } 4132114402Sru else { 4133114402Sru if (is_on) { 4134114402Sru out->on(); 4135114402Sru // lastly we reset the output registers 4136114402Sru reset_output_registers(); 4137114402Sru } 4138114402Sru else 4139114402Sru out->off(); 4140114402Sru suppress_start_page = current_page; 4141114402Sru } 4142114402Sru } 4143114402Sru} 4144114402Sru 4145114402Sruint suppress_node::force_tprint() 4146114402Sru{ 4147114402Sru return is_on; 4148114402Sru} 4149114402Sru 4150151497Sruint suppress_node::is_tag() 4151151497Sru{ 4152151497Sru return is_on; 4153151497Sru} 4154151497Sru 4155114402Sruhunits suppress_node::width() 4156114402Sru{ 4157114402Sru return H0; 4158114402Sru} 4159114402Sru 4160114402Sru/* composite_node */ 4161114402Sru 4162114402Sruclass composite_node : public charinfo_node { 4163114402Sru node *n; 4164114402Sru tfont *tf; 4165114402Srupublic: 4166151497Sru composite_node(node *, charinfo *, tfont *, statem *, int, node * = 0); 4167114402Sru ~composite_node(); 4168114402Sru node *copy(); 4169114402Sru hunits width(); 4170114402Sru node *last_char_node(); 4171114402Sru units size(); 4172114402Sru void tprint(troff_output_file *); 4173114402Sru hyphenation_type get_hyphenation_type(); 4174114402Sru void ascii_print(ascii_output_file *); 4175114402Sru void asciify(macro *); 4176114402Sru hyphen_list *get_hyphen_list(hyphen_list *, int *); 4177114402Sru node *add_self(node *, hyphen_list **); 4178114402Sru tfont *get_tfont(); 4179114402Sru int same(node *); 4180114402Sru const char *type(); 4181114402Sru int force_tprint(); 4182151497Sru int is_tag(); 4183114402Sru void vertical_extent(vunits *, vunits *); 4184114402Sru vunits vertical_width(); 4185114402Sru}; 4186114402Sru 4187151497Srucomposite_node::composite_node(node *p, charinfo *c, tfont *t, statem *s, 4188151497Sru int pop, node *x) 4189151497Sru: charinfo_node(c, s, pop, x), n(p), tf(t) 4190114402Sru{ 4191114402Sru} 4192114402Sru 4193114402Srucomposite_node::~composite_node() 4194114402Sru{ 4195114402Sru delete_node_list(n); 4196114402Sru} 4197114402Sru 4198114402Srunode *composite_node::copy() 4199114402Sru{ 4200151497Sru return new composite_node(copy_node_list(n), ci, tf, state, div_nest_level); 4201114402Sru} 4202114402Sru 4203114402Sruhunits composite_node::width() 4204114402Sru{ 4205114402Sru hunits x; 4206114402Sru if (tf->get_constant_space(&x)) 4207114402Sru return x; 4208114402Sru x = H0; 4209114402Sru for (node *tem = n; tem; tem = tem->next) 4210114402Sru x += tem->width(); 4211114402Sru hunits offset; 4212114402Sru if (tf->get_bold(&offset)) 4213114402Sru x += offset; 4214114402Sru x += tf->get_track_kern(); 4215114402Sru return x; 4216114402Sru} 4217114402Sru 4218114402Srunode *composite_node::last_char_node() 4219114402Sru{ 4220114402Sru return this; 4221114402Sru} 4222114402Sru 4223114402Sruvunits composite_node::vertical_width() 4224114402Sru{ 4225114402Sru vunits v = V0; 4226114402Sru for (node *tem = n; tem; tem = tem->next) 4227114402Sru v += tem->vertical_width(); 4228114402Sru return v; 4229114402Sru} 4230114402Sru 4231114402Sruunits composite_node::size() 4232114402Sru{ 4233114402Sru return tf->get_size().to_units(); 4234114402Sru} 4235114402Sru 4236114402Sruhyphenation_type composite_node::get_hyphenation_type() 4237114402Sru{ 4238114402Sru return HYPHEN_MIDDLE; 4239114402Sru} 4240114402Sru 4241114402Sruvoid composite_node::asciify(macro *m) 4242114402Sru{ 4243114402Sru unsigned char c = ci->get_asciify_code(); 4244114402Sru if (c == 0) 4245114402Sru c = ci->get_ascii_code(); 4246114402Sru if (c != 0) { 4247114402Sru m->append(c); 4248114402Sru delete this; 4249114402Sru } 4250114402Sru else 4251114402Sru m->append(this); 4252114402Sru} 4253114402Sru 4254114402Sruvoid composite_node::ascii_print(ascii_output_file *ascii) 4255114402Sru{ 4256114402Sru unsigned char c = ci->get_ascii_code(); 4257114402Sru if (c != 0) 4258114402Sru ascii->outc(c); 4259114402Sru else 4260114402Sru ascii->outs(ci->nm.contents()); 4261114402Sru 4262114402Sru} 4263114402Sru 4264114402Sruhyphen_list *composite_node::get_hyphen_list(hyphen_list *tail, int *count) 4265114402Sru{ 4266114402Sru (*count)++; 4267114402Sru return new hyphen_list(ci->get_hyphenation_code(), tail); 4268114402Sru} 4269114402Sru 4270114402Srunode *composite_node::add_self(node *nn, hyphen_list **p) 4271114402Sru{ 4272114402Sru assert(ci->get_hyphenation_code() == (*p)->hyphenation_code); 4273114402Sru next = nn; 4274114402Sru nn = this; 4275114402Sru if ((*p)->hyphen) 4276114402Sru nn = nn->add_discretionary_hyphen(); 4277114402Sru hyphen_list *pp = *p; 4278114402Sru *p = (*p)->next; 4279114402Sru delete pp; 4280114402Sru return nn; 4281114402Sru} 4282114402Sru 4283114402Srutfont *composite_node::get_tfont() 4284114402Sru{ 4285114402Sru return tf; 4286114402Sru} 4287114402Sru 4288114402Srunode *reverse_node_list(node *n) 4289114402Sru{ 4290114402Sru node *r = 0; 4291114402Sru while (n) { 4292114402Sru node *tem = n; 4293114402Sru n = n->next; 4294114402Sru tem->next = r; 4295114402Sru r = tem; 4296114402Sru } 4297114402Sru return r; 4298114402Sru} 4299114402Sru 4300151497Sruvoid composite_node::vertical_extent(vunits *minimum, vunits *maximum) 4301114402Sru{ 4302114402Sru n = reverse_node_list(n); 4303151497Sru node_list_vertical_extent(n, minimum, maximum); 4304114402Sru n = reverse_node_list(n); 4305114402Sru} 4306114402Sru 4307114402Sruwidth_list::width_list(hunits w, hunits s) 4308114402Sru: width(w), sentence_width(s), next(0) 4309114402Sru{ 4310114402Sru} 4311114402Sru 4312114402Sruwidth_list::width_list(width_list *w) 4313114402Sru: width(w->width), sentence_width(w->sentence_width), next(0) 4314114402Sru{ 4315114402Sru} 4316114402Sru 4317114402Sruword_space_node::word_space_node(hunits d, color *c, width_list *w, node *x) 4318114402Sru: space_node(d, c, x), orig_width(w), unformat(0) 4319114402Sru{ 4320114402Sru} 4321114402Sru 4322114402Sruword_space_node::word_space_node(hunits d, int s, color *c, width_list *w, 4323151497Sru int flag, statem *st, int pop, node *x) 4324151497Sru: space_node(d, s, 0, c, st, pop, x), orig_width(w), unformat(flag) 4325114402Sru{ 4326114402Sru} 4327114402Sru 4328114402Sruword_space_node::~word_space_node() 4329114402Sru{ 4330114402Sru width_list *w = orig_width; 4331114402Sru while (w != 0) { 4332114402Sru width_list *tmp = w; 4333114402Sru w = w->next; 4334114402Sru delete tmp; 4335114402Sru } 4336114402Sru} 4337114402Sru 4338114402Srunode *word_space_node::copy() 4339114402Sru{ 4340114402Sru assert(orig_width != 0); 4341114402Sru width_list *w_old_curr = orig_width; 4342114402Sru width_list *w_new_curr = new width_list(w_old_curr); 4343114402Sru width_list *w_new = w_new_curr; 4344114402Sru w_old_curr = w_old_curr->next; 4345114402Sru while (w_old_curr != 0) { 4346114402Sru w_new_curr->next = new width_list(w_old_curr); 4347114402Sru w_new_curr = w_new_curr->next; 4348114402Sru w_old_curr = w_old_curr->next; 4349114402Sru } 4350151497Sru return new word_space_node(n, set, col, w_new, unformat, state, 4351151497Sru div_nest_level); 4352114402Sru} 4353114402Sru 4354114402Sruint word_space_node::set_unformat_flag() 4355114402Sru{ 4356114402Sru unformat = 1; 4357114402Sru return 1; 4358114402Sru} 4359114402Sru 4360114402Sruvoid word_space_node::tprint(troff_output_file *out) 4361114402Sru{ 4362114402Sru out->fill_color(col); 4363114402Sru out->word_marker(); 4364114402Sru out->right(n); 4365114402Sru} 4366114402Sru 4367114402Sruint word_space_node::merge_space(hunits h, hunits sw, hunits ssw) 4368114402Sru{ 4369114402Sru n += h; 4370114402Sru assert(orig_width != 0); 4371114402Sru width_list *w = orig_width; 4372114402Sru for (; w->next; w = w->next) 4373114402Sru ; 4374114402Sru w->next = new width_list(sw, ssw); 4375114402Sru return 1; 4376114402Sru} 4377114402Sru 4378114402Sruunbreakable_space_node::unbreakable_space_node(hunits d, color *c, node *x) 4379114402Sru: word_space_node(d, c, 0, x) 4380114402Sru{ 4381114402Sru} 4382114402Sru 4383114402Sruunbreakable_space_node::unbreakable_space_node(hunits d, int s, 4384151497Sru color *c, statem *st, int pop, 4385151497Sru node *x) 4386151497Sru: word_space_node(d, s, c, 0, 0, st, pop, x) 4387114402Sru{ 4388114402Sru} 4389114402Sru 4390114402Srunode *unbreakable_space_node::copy() 4391114402Sru{ 4392151497Sru return new unbreakable_space_node(n, set, col, state, div_nest_level); 4393114402Sru} 4394114402Sru 4395114402Sruint unbreakable_space_node::force_tprint() 4396114402Sru{ 4397114402Sru return 0; 4398114402Sru} 4399114402Sru 4400151497Sruint unbreakable_space_node::is_tag() 4401151497Sru{ 4402151497Sru return 0; 4403151497Sru} 4404151497Sru 4405114402Srubreakpoint *unbreakable_space_node::get_breakpoints(hunits, int, 4406114402Sru breakpoint *rest, int) 4407114402Sru{ 4408114402Sru return rest; 4409114402Sru} 4410114402Sru 4411114402Sruint unbreakable_space_node::nbreaks() 4412114402Sru{ 4413114402Sru return 0; 4414114402Sru} 4415114402Sru 4416114402Sruvoid unbreakable_space_node::split(int, node **, node **) 4417114402Sru{ 4418114402Sru assert(0); 4419114402Sru} 4420114402Sru 4421114402Sruint unbreakable_space_node::merge_space(hunits, hunits, hunits) 4422114402Sru{ 4423114402Sru return 0; 4424114402Sru} 4425114402Sru 4426114402Sruhvpair::hvpair() 4427114402Sru{ 4428114402Sru} 4429114402Sru 4430114402Srudraw_node::draw_node(char c, hvpair *p, int np, font_size s, 4431114402Sru color *gc, color *fc) 4432114402Sru: npoints(np), sz(s), gcol(gc), fcol(fc), code(c) 4433114402Sru{ 4434114402Sru point = new hvpair[npoints]; 4435114402Sru for (int i = 0; i < npoints; i++) 4436114402Sru point[i] = p[i]; 4437114402Sru} 4438114402Sru 4439151497Srudraw_node::draw_node(char c, hvpair *p, int np, font_size s, 4440151497Sru color *gc, color *fc, statem *st, int pop) 4441151497Sru: node(0, st, pop), npoints(np), sz(s), gcol(gc), fcol(fc), code(c) 4442151497Sru{ 4443151497Sru point = new hvpair[npoints]; 4444151497Sru for (int i = 0; i < npoints; i++) 4445151497Sru point[i] = p[i]; 4446151497Sru} 4447151497Sru 4448114402Sruint draw_node::same(node *n) 4449114402Sru{ 4450114402Sru draw_node *nd = (draw_node *)n; 4451114402Sru if (code != nd->code || npoints != nd->npoints || sz != nd->sz 4452114402Sru || gcol != nd->gcol || fcol != nd->fcol) 4453114402Sru return 0; 4454114402Sru for (int i = 0; i < npoints; i++) 4455114402Sru if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v) 4456114402Sru return 0; 4457114402Sru return 1; 4458114402Sru} 4459114402Sru 4460114402Sruconst char *draw_node::type() 4461114402Sru{ 4462114402Sru return "draw_node"; 4463114402Sru} 4464114402Sru 4465114402Sruint draw_node::force_tprint() 4466114402Sru{ 4467114402Sru return 0; 4468114402Sru} 4469114402Sru 4470151497Sruint draw_node::is_tag() 4471151497Sru{ 4472151497Sru return 0; 4473151497Sru} 4474151497Sru 4475114402Srudraw_node::~draw_node() 4476114402Sru{ 4477114402Sru if (point) 4478114402Sru a_delete point; 4479114402Sru} 4480114402Sru 4481114402Sruhunits draw_node::width() 4482114402Sru{ 4483114402Sru hunits x = H0; 4484114402Sru for (int i = 0; i < npoints; i++) 4485114402Sru x += point[i].h; 4486114402Sru return x; 4487114402Sru} 4488114402Sru 4489114402Sruvunits draw_node::vertical_width() 4490114402Sru{ 4491114402Sru if (code == 'e') 4492114402Sru return V0; 4493114402Sru vunits x = V0; 4494114402Sru for (int i = 0; i < npoints; i++) 4495114402Sru x += point[i].v; 4496114402Sru return x; 4497114402Sru} 4498114402Sru 4499114402Srunode *draw_node::copy() 4500114402Sru{ 4501151497Sru return new draw_node(code, point, npoints, sz, gcol, fcol, state, 4502151497Sru div_nest_level); 4503114402Sru} 4504114402Sru 4505114402Sruvoid draw_node::tprint(troff_output_file *out) 4506114402Sru{ 4507114402Sru out->draw(code, point, npoints, sz, gcol, fcol); 4508114402Sru} 4509114402Sru 4510114402Sru/* tprint methods */ 4511114402Sru 4512114402Sruvoid glyph_node::tprint(troff_output_file *out) 4513114402Sru{ 4514114402Sru tfont *ptf = tf->get_plain(); 4515114402Sru if (ptf == tf) 4516114402Sru out->put_char_width(ci, ptf, gcol, fcol, width(), H0); 4517114402Sru else { 4518114402Sru hunits offset; 4519114402Sru int bold = tf->get_bold(&offset); 4520114402Sru hunits w = ptf->get_width(ci); 4521114402Sru hunits k = H0; 4522114402Sru hunits x; 4523114402Sru int cs = tf->get_constant_space(&x); 4524114402Sru if (cs) { 4525114402Sru x -= w; 4526114402Sru if (bold) 4527114402Sru x -= offset; 4528114402Sru hunits x2 = x/2; 4529114402Sru out->right(x2); 4530114402Sru k = x - x2; 4531114402Sru } 4532114402Sru else 4533114402Sru k = tf->get_track_kern(); 4534114402Sru if (bold) { 4535114402Sru out->put_char(ci, ptf, gcol, fcol); 4536114402Sru out->right(offset); 4537114402Sru } 4538114402Sru out->put_char_width(ci, ptf, gcol, fcol, w, k); 4539114402Sru } 4540114402Sru} 4541114402Sru 4542114402Sruvoid glyph_node::zero_width_tprint(troff_output_file *out) 4543114402Sru{ 4544114402Sru tfont *ptf = tf->get_plain(); 4545114402Sru hunits offset; 4546114402Sru int bold = tf->get_bold(&offset); 4547114402Sru hunits x; 4548114402Sru int cs = tf->get_constant_space(&x); 4549114402Sru if (cs) { 4550114402Sru x -= ptf->get_width(ci); 4551114402Sru if (bold) 4552114402Sru x -= offset; 4553114402Sru x = x/2; 4554114402Sru out->right(x); 4555114402Sru } 4556114402Sru out->put_char(ci, ptf, gcol, fcol); 4557114402Sru if (bold) { 4558114402Sru out->right(offset); 4559114402Sru out->put_char(ci, ptf, gcol, fcol); 4560114402Sru out->right(-offset); 4561114402Sru } 4562114402Sru if (cs) 4563114402Sru out->right(-x); 4564114402Sru} 4565114402Sru 4566114402Sruvoid break_char_node::tprint(troff_output_file *t) 4567114402Sru{ 4568114402Sru ch->tprint(t); 4569114402Sru} 4570114402Sru 4571114402Sruvoid break_char_node::zero_width_tprint(troff_output_file *t) 4572114402Sru{ 4573114402Sru ch->zero_width_tprint(t); 4574114402Sru} 4575114402Sru 4576114402Sruvoid hline_node::tprint(troff_output_file *out) 4577114402Sru{ 4578114402Sru if (x < H0) { 4579114402Sru out->right(x); 4580114402Sru x = -x; 4581114402Sru } 4582114402Sru if (n == 0) { 4583114402Sru out->right(x); 4584114402Sru return; 4585114402Sru } 4586114402Sru hunits w = n->width(); 4587114402Sru if (w <= H0) { 4588114402Sru error("horizontal line drawing character must have positive width"); 4589114402Sru out->right(x); 4590114402Sru return; 4591114402Sru } 4592114402Sru int i = int(x/w); 4593114402Sru if (i == 0) { 4594114402Sru hunits xx = x - w; 4595114402Sru hunits xx2 = xx/2; 4596114402Sru out->right(xx2); 4597114402Sru if (out->is_on()) 4598114402Sru n->tprint(out); 4599114402Sru out->right(xx - xx2); 4600114402Sru } 4601114402Sru else { 4602114402Sru hunits rem = x - w*i; 4603257263Ssbruno if (rem > H0) { 4604114402Sru if (n->overlaps_horizontally()) { 4605114402Sru if (out->is_on()) 4606114402Sru n->tprint(out); 4607114402Sru out->right(rem - w); 4608257263Ssbruno } else 4609114402Sru out->right(rem); 4610257263Ssbruno } 4611114402Sru while (--i >= 0) 4612114402Sru if (out->is_on()) 4613114402Sru n->tprint(out); 4614114402Sru } 4615114402Sru} 4616114402Sru 4617114402Sruvoid vline_node::tprint(troff_output_file *out) 4618114402Sru{ 4619114402Sru if (n == 0) { 4620114402Sru out->down(x); 4621114402Sru return; 4622114402Sru } 4623114402Sru vunits h = n->size(); 4624114402Sru int overlaps = n->overlaps_vertically(); 4625114402Sru vunits y = x; 4626114402Sru if (y < V0) { 4627114402Sru y = -y; 4628114402Sru int i = y / h; 4629114402Sru vunits rem = y - i*h; 4630114402Sru if (i == 0) { 4631114402Sru out->right(n->width()); 4632114402Sru out->down(-rem); 4633114402Sru } 4634114402Sru else { 4635114402Sru while (--i > 0) { 4636114402Sru n->zero_width_tprint(out); 4637114402Sru out->down(-h); 4638114402Sru } 4639114402Sru if (overlaps) { 4640114402Sru n->zero_width_tprint(out); 4641114402Sru out->down(-rem); 4642114402Sru if (out->is_on()) 4643114402Sru n->tprint(out); 4644114402Sru out->down(-h); 4645114402Sru } 4646114402Sru else { 4647114402Sru if (out->is_on()) 4648114402Sru n->tprint(out); 4649114402Sru out->down(-h - rem); 4650114402Sru } 4651114402Sru } 4652114402Sru } 4653114402Sru else { 4654114402Sru int i = y / h; 4655114402Sru vunits rem = y - i*h; 4656114402Sru if (i == 0) { 4657114402Sru out->down(rem); 4658114402Sru out->right(n->width()); 4659114402Sru } 4660114402Sru else { 4661114402Sru out->down(h); 4662114402Sru if (overlaps) 4663114402Sru n->zero_width_tprint(out); 4664114402Sru out->down(rem); 4665114402Sru while (--i > 0) { 4666114402Sru n->zero_width_tprint(out); 4667114402Sru out->down(h); 4668114402Sru } 4669114402Sru if (out->is_on()) 4670114402Sru n->tprint(out); 4671114402Sru } 4672114402Sru } 4673114402Sru} 4674114402Sru 4675114402Sruvoid zero_width_node::tprint(troff_output_file *out) 4676114402Sru{ 4677114402Sru if (!n) 4678114402Sru return; 4679114402Sru if (!n->next) { 4680114402Sru n->zero_width_tprint(out); 4681114402Sru return; 4682114402Sru } 4683114402Sru int hpos = out->get_hpos(); 4684114402Sru int vpos = out->get_vpos(); 4685114402Sru node *tem = n; 4686114402Sru while (tem) { 4687114402Sru tem->tprint(out); 4688114402Sru tem = tem->next; 4689114402Sru } 4690114402Sru out->moveto(hpos, vpos); 4691114402Sru} 4692114402Sru 4693114402Sruvoid overstrike_node::tprint(troff_output_file *out) 4694114402Sru{ 4695114402Sru hunits pos = H0; 4696114402Sru for (node *tem = list; tem; tem = tem->next) { 4697114402Sru hunits x = (max_width - tem->width())/2; 4698114402Sru out->right(x - pos); 4699114402Sru pos = x; 4700114402Sru tem->zero_width_tprint(out); 4701114402Sru } 4702114402Sru out->right(max_width - pos); 4703114402Sru} 4704114402Sru 4705114402Sruvoid bracket_node::tprint(troff_output_file *out) 4706114402Sru{ 4707114402Sru if (list == 0) 4708114402Sru return; 4709114402Sru int npieces = 0; 4710114402Sru node *tem; 4711114402Sru for (tem = list; tem; tem = tem->next) 4712114402Sru ++npieces; 4713114402Sru vunits h = list->size(); 4714114402Sru vunits totalh = h*npieces; 4715114402Sru vunits y = (totalh - h)/2; 4716114402Sru out->down(y); 4717114402Sru for (tem = list; tem; tem = tem->next) { 4718114402Sru tem->zero_width_tprint(out); 4719114402Sru out->down(-h); 4720114402Sru } 4721114402Sru out->right(max_width); 4722114402Sru out->down(totalh - y); 4723114402Sru} 4724114402Sru 4725114402Sruvoid node::tprint(troff_output_file *) 4726114402Sru{ 4727114402Sru} 4728114402Sru 4729114402Sruvoid node::zero_width_tprint(troff_output_file *out) 4730114402Sru{ 4731114402Sru int hpos = out->get_hpos(); 4732114402Sru int vpos = out->get_vpos(); 4733114402Sru tprint(out); 4734114402Sru out->moveto(hpos, vpos); 4735114402Sru} 4736114402Sru 4737114402Sruvoid space_node::tprint(troff_output_file *out) 4738114402Sru{ 4739114402Sru out->fill_color(col); 4740114402Sru out->right(n); 4741114402Sru} 4742114402Sru 4743114402Sruvoid hmotion_node::tprint(troff_output_file *out) 4744114402Sru{ 4745114402Sru out->fill_color(col); 4746114402Sru out->right(n); 4747114402Sru} 4748114402Sru 4749114402Sruvoid space_char_hmotion_node::tprint(troff_output_file *out) 4750114402Sru{ 4751114402Sru out->fill_color(col); 4752114402Sru if (is_html) { 4753114402Sru // we emit the space width as a negative glyph index 4754114402Sru out->flush_tbuf(); 4755114402Sru out->do_motion(); 4756114402Sru out->put('N'); 4757114402Sru out->put(-n.to_units()); 4758114402Sru out->put('\n'); 4759114402Sru } 4760114402Sru out->right(n); 4761114402Sru} 4762114402Sru 4763114402Sruvoid vmotion_node::tprint(troff_output_file *out) 4764114402Sru{ 4765114402Sru out->fill_color(col); 4766114402Sru out->down(n); 4767114402Sru} 4768114402Sru 4769114402Sruvoid kern_pair_node::tprint(troff_output_file *out) 4770114402Sru{ 4771114402Sru n1->tprint(out); 4772114402Sru out->right(amount); 4773114402Sru n2->tprint(out); 4774114402Sru} 4775114402Sru 4776114402Srustatic void tprint_reverse_node_list(troff_output_file *out, node *n) 4777114402Sru{ 4778114402Sru if (n == 0) 4779114402Sru return; 4780114402Sru tprint_reverse_node_list(out, n->next); 4781114402Sru n->tprint(out); 4782114402Sru} 4783114402Sru 4784114402Sruvoid dbreak_node::tprint(troff_output_file *out) 4785114402Sru{ 4786114402Sru tprint_reverse_node_list(out, none); 4787114402Sru} 4788114402Sru 4789114402Sruvoid composite_node::tprint(troff_output_file *out) 4790114402Sru{ 4791114402Sru hunits bold_offset; 4792114402Sru int is_bold = tf->get_bold(&bold_offset); 4793114402Sru hunits track_kern = tf->get_track_kern(); 4794114402Sru hunits constant_space; 4795114402Sru int is_constant_spaced = tf->get_constant_space(&constant_space); 4796114402Sru hunits x = H0; 4797114402Sru if (is_constant_spaced) { 4798114402Sru x = constant_space; 4799114402Sru for (node *tem = n; tem; tem = tem->next) 4800114402Sru x -= tem->width(); 4801114402Sru if (is_bold) 4802114402Sru x -= bold_offset; 4803114402Sru hunits x2 = x/2; 4804114402Sru out->right(x2); 4805114402Sru x -= x2; 4806114402Sru } 4807114402Sru if (is_bold) { 4808114402Sru int hpos = out->get_hpos(); 4809114402Sru int vpos = out->get_vpos(); 4810114402Sru tprint_reverse_node_list(out, n); 4811114402Sru out->moveto(hpos, vpos); 4812114402Sru out->right(bold_offset); 4813114402Sru } 4814114402Sru tprint_reverse_node_list(out, n); 4815114402Sru if (is_constant_spaced) 4816114402Sru out->right(x); 4817114402Sru else 4818114402Sru out->right(track_kern); 4819114402Sru} 4820114402Sru 4821114402Srunode *make_composite_node(charinfo *s, environment *env) 4822114402Sru{ 4823114402Sru int fontno = env_definite_font(env); 4824114402Sru if (fontno < 0) { 4825114402Sru error("no current font"); 4826114402Sru return 0; 4827114402Sru } 4828114402Sru assert(fontno < font_table_size && font_table[fontno] != 0); 4829114402Sru node *n = charinfo_to_node_list(s, env); 4830114402Sru font_size fs = env->get_font_size(); 4831114402Sru int char_height = env->get_char_height(); 4832114402Sru int char_slant = env->get_char_slant(); 4833114402Sru tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, 4834114402Sru fontno); 4835114402Sru if (env->is_composite()) 4836114402Sru tf = tf->get_plain(); 4837151497Sru return new composite_node(n, s, tf, 0, 0, 0); 4838114402Sru} 4839114402Sru 4840114402Srunode *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0) 4841114402Sru{ 4842114402Sru int fontno = env_definite_font(env); 4843114402Sru if (fontno < 0) { 4844114402Sru error("no current font"); 4845114402Sru return 0; 4846114402Sru } 4847114402Sru assert(fontno < font_table_size && font_table[fontno] != 0); 4848114402Sru int fn = fontno; 4849114402Sru int found = font_table[fontno]->contains(s); 4850114402Sru if (!found) { 4851114402Sru macro *mac = s->get_macro(); 4852114402Sru if (mac && s->is_fallback()) 4853114402Sru return make_composite_node(s, env); 4854114402Sru if (s->numbered()) { 4855114402Sru if (!no_error_message) 4856114402Sru warning(WARN_CHAR, "can't find numbered character %1", 4857114402Sru s->get_number()); 4858114402Sru return 0; 4859114402Sru } 4860114402Sru special_font_list *sf = font_table[fontno]->sf; 4861114402Sru while (sf != 0 && !found) { 4862114402Sru fn = sf->n; 4863114402Sru if (font_table[fn]) 4864114402Sru found = font_table[fn]->contains(s); 4865114402Sru sf = sf->next; 4866114402Sru } 4867114402Sru if (!found) { 4868114402Sru symbol f = font_table[fontno]->get_name(); 4869114402Sru string gl(f.contents()); 4870114402Sru gl += ' '; 4871114402Sru gl += s->nm.contents(); 4872114402Sru gl += '\0'; 4873114402Sru charinfo *ci = get_charinfo(symbol(gl.contents())); 4874114402Sru if (ci && ci->get_macro()) 4875114402Sru return make_composite_node(ci, env); 4876114402Sru } 4877114402Sru if (!found) { 4878114402Sru sf = global_special_fonts; 4879114402Sru while (sf != 0 && !found) { 4880114402Sru fn = sf->n; 4881114402Sru if (font_table[fn]) 4882114402Sru found = font_table[fn]->contains(s); 4883114402Sru sf = sf->next; 4884114402Sru } 4885114402Sru } 4886114402Sru if (!found) 4887114402Sru if (mac && s->is_special()) 4888114402Sru return make_composite_node(s, env); 4889114402Sru if (!found) { 4890114402Sru for (fn = 0; fn < font_table_size; fn++) 4891114402Sru if (font_table[fn] 4892114402Sru && font_table[fn]->is_special() 4893114402Sru && font_table[fn]->contains(s)) { 4894114402Sru found = 1; 4895114402Sru break; 4896114402Sru } 4897114402Sru } 4898114402Sru if (!found) { 4899114402Sru if (!no_error_message && s->first_time_not_found()) { 4900114402Sru unsigned char input_code = s->get_ascii_code(); 4901114402Sru if (input_code != 0) { 4902114402Sru if (csgraph(input_code)) 4903114402Sru warning(WARN_CHAR, "can't find character `%1'", input_code); 4904114402Sru else 4905114402Sru warning(WARN_CHAR, "can't find character with input code %1", 4906114402Sru int(input_code)); 4907114402Sru } 4908114402Sru else if (s->nm.contents()) 4909114402Sru warning(WARN_CHAR, "can't find special character `%1'", 4910114402Sru s->nm.contents()); 4911114402Sru } 4912114402Sru return 0; 4913114402Sru } 4914114402Sru } 4915114402Sru font_size fs = env->get_font_size(); 4916114402Sru int char_height = env->get_char_height(); 4917114402Sru int char_slant = env->get_char_slant(); 4918114402Sru tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn); 4919114402Sru if (env->is_composite()) 4920114402Sru tf = tf->get_plain(); 4921114402Sru color *gcol = env->get_glyph_color(); 4922114402Sru color *fcol = env->get_fill_color(); 4923151497Sru return new glyph_node(s, tf, gcol, fcol, 0, 0); 4924114402Sru} 4925114402Sru 4926114402Srunode *make_node(charinfo *ci, environment *env) 4927114402Sru{ 4928114402Sru switch (ci->get_special_translation()) { 4929114402Sru case charinfo::TRANSLATE_SPACE: 4930114402Sru return new space_char_hmotion_node(env->get_space_width(), 4931114402Sru env->get_fill_color()); 4932114402Sru case charinfo::TRANSLATE_STRETCHABLE_SPACE: 4933114402Sru return new unbreakable_space_node(env->get_space_width(), 4934114402Sru env->get_fill_color()); 4935114402Sru case charinfo::TRANSLATE_DUMMY: 4936114402Sru return new dummy_node; 4937114402Sru case charinfo::TRANSLATE_HYPHEN_INDICATOR: 4938114402Sru error("translation to \\% ignored in this context"); 4939114402Sru break; 4940114402Sru } 4941114402Sru charinfo *tem = ci->get_translation(); 4942114402Sru if (tem) 4943114402Sru ci = tem; 4944114402Sru macro *mac = ci->get_macro(); 4945114402Sru if (mac && ci->is_normal()) 4946114402Sru return make_composite_node(ci, env); 4947114402Sru else 4948114402Sru return make_glyph_node(ci, env); 4949114402Sru} 4950114402Sru 4951114402Sruint character_exists(charinfo *ci, environment *env) 4952114402Sru{ 4953114402Sru if (ci->get_special_translation() != charinfo::TRANSLATE_NONE) 4954114402Sru return 1; 4955114402Sru charinfo *tem = ci->get_translation(); 4956114402Sru if (tem) 4957114402Sru ci = tem; 4958114402Sru if (ci->get_macro()) 4959114402Sru return 1; 4960114402Sru node *nd = make_glyph_node(ci, env, 1); 4961114402Sru if (nd) { 4962114402Sru delete nd; 4963114402Sru return 1; 4964114402Sru } 4965114402Sru return 0; 4966114402Sru} 4967114402Sru 4968114402Srunode *node::add_char(charinfo *ci, environment *env, 4969151497Sru hunits *widthp, int *spacep, node **glyph_comp_np) 4970114402Sru{ 4971114402Sru node *res; 4972114402Sru switch (ci->get_special_translation()) { 4973114402Sru case charinfo::TRANSLATE_SPACE: 4974114402Sru res = new space_char_hmotion_node(env->get_space_width(), 4975114402Sru env->get_fill_color(), this); 4976114402Sru *widthp += res->width(); 4977114402Sru return res; 4978114402Sru case charinfo::TRANSLATE_STRETCHABLE_SPACE: 4979114402Sru res = new unbreakable_space_node(env->get_space_width(), 4980114402Sru env->get_fill_color(), this); 4981114402Sru res->freeze_space(); 4982114402Sru *widthp += res->width(); 4983114402Sru *spacep += res->nspaces(); 4984114402Sru return res; 4985114402Sru case charinfo::TRANSLATE_DUMMY: 4986114402Sru return new dummy_node(this); 4987114402Sru case charinfo::TRANSLATE_HYPHEN_INDICATOR: 4988114402Sru return add_discretionary_hyphen(); 4989114402Sru } 4990114402Sru charinfo *tem = ci->get_translation(); 4991114402Sru if (tem) 4992114402Sru ci = tem; 4993114402Sru macro *mac = ci->get_macro(); 4994114402Sru if (mac && ci->is_normal()) { 4995114402Sru res = make_composite_node(ci, env); 4996114402Sru if (res) { 4997114402Sru res->next = this; 4998114402Sru *widthp += res->width(); 4999151497Sru if (glyph_comp_np) 5000151497Sru *glyph_comp_np = res; 5001114402Sru } 5002151497Sru else { 5003151497Sru if (glyph_comp_np) 5004151497Sru *glyph_comp_np = res; 5005114402Sru return this; 5006151497Sru } 5007114402Sru } 5008114402Sru else { 5009114402Sru node *gn = make_glyph_node(ci, env); 5010114402Sru if (gn == 0) 5011114402Sru return this; 5012114402Sru else { 5013114402Sru hunits old_width = width(); 5014114402Sru node *p = gn->merge_self(this); 5015114402Sru if (p == 0) { 5016114402Sru *widthp += gn->width(); 5017114402Sru gn->next = this; 5018114402Sru res = gn; 5019114402Sru } 5020114402Sru else { 5021114402Sru *widthp += p->width() - old_width; 5022114402Sru res = p; 5023114402Sru } 5024151497Sru if (glyph_comp_np) 5025151497Sru *glyph_comp_np = res; 5026114402Sru } 5027114402Sru } 5028114402Sru int break_code = 0; 5029114402Sru if (ci->can_break_before()) 5030114402Sru break_code = 1; 5031114402Sru if (ci->can_break_after()) 5032114402Sru break_code |= 2; 5033114402Sru if (break_code) { 5034114402Sru node *next1 = res->next; 5035114402Sru res->next = 0; 5036114402Sru res = new break_char_node(res, break_code, env->get_fill_color(), next1); 5037114402Sru } 5038114402Sru return res; 5039114402Sru} 5040114402Sru 5041114402Sru#ifdef __GNUG__ 5042114402Sruinline 5043114402Sru#endif 5044114402Sruint same_node(node *n1, node *n2) 5045114402Sru{ 5046114402Sru if (n1 != 0) { 5047114402Sru if (n2 != 0) 5048114402Sru return n1->type() == n2->type() && n1->same(n2); 5049114402Sru else 5050114402Sru return 0; 5051114402Sru } 5052114402Sru else 5053114402Sru return n2 == 0; 5054114402Sru} 5055114402Sru 5056114402Sruint same_node_list(node *n1, node *n2) 5057114402Sru{ 5058114402Sru while (n1 && n2) { 5059114402Sru if (n1->type() != n2->type() || !n1->same(n2)) 5060114402Sru return 0; 5061114402Sru n1 = n1->next; 5062114402Sru n2 = n2->next; 5063114402Sru } 5064114402Sru return !n1 && !n2; 5065114402Sru} 5066114402Sru 5067114402Sruint extra_size_node::same(node *nd) 5068114402Sru{ 5069114402Sru return n == ((extra_size_node *)nd)->n; 5070114402Sru} 5071114402Sru 5072114402Sruconst char *extra_size_node::type() 5073114402Sru{ 5074114402Sru return "extra_size_node"; 5075114402Sru} 5076114402Sru 5077114402Sruint extra_size_node::force_tprint() 5078114402Sru{ 5079114402Sru return 0; 5080114402Sru} 5081114402Sru 5082151497Sruint extra_size_node::is_tag() 5083151497Sru{ 5084151497Sru return 0; 5085151497Sru} 5086151497Sru 5087114402Sruint vertical_size_node::same(node *nd) 5088114402Sru{ 5089114402Sru return n == ((vertical_size_node *)nd)->n; 5090114402Sru} 5091114402Sru 5092114402Sruconst char *vertical_size_node::type() 5093114402Sru{ 5094114402Sru return "vertical_size_node"; 5095114402Sru} 5096114402Sru 5097114402Sruint vertical_size_node::set_unformat_flag() 5098114402Sru{ 5099114402Sru return 0; 5100114402Sru} 5101114402Sru 5102114402Sruint vertical_size_node::force_tprint() 5103114402Sru{ 5104114402Sru return 0; 5105114402Sru} 5106114402Sru 5107151497Sruint vertical_size_node::is_tag() 5108151497Sru{ 5109151497Sru return 0; 5110151497Sru} 5111151497Sru 5112114402Sruint hmotion_node::same(node *nd) 5113114402Sru{ 5114114402Sru return n == ((hmotion_node *)nd)->n 5115114402Sru && col == ((hmotion_node *)nd)->col; 5116114402Sru} 5117114402Sru 5118114402Sruconst char *hmotion_node::type() 5119114402Sru{ 5120114402Sru return "hmotion_node"; 5121114402Sru} 5122114402Sru 5123114402Sruint hmotion_node::set_unformat_flag() 5124114402Sru{ 5125114402Sru unformat = 1; 5126114402Sru return 1; 5127114402Sru} 5128114402Sru 5129114402Sruint hmotion_node::force_tprint() 5130114402Sru{ 5131114402Sru return 0; 5132114402Sru} 5133114402Sru 5134151497Sruint hmotion_node::is_tag() 5135114402Sru{ 5136151497Sru return 0; 5137151497Sru} 5138151497Sru 5139151497Srunode *hmotion_node::add_self(node *nd, hyphen_list **p) 5140151497Sru{ 5141151497Sru next = nd; 5142114402Sru hyphen_list *pp = *p; 5143114402Sru *p = (*p)->next; 5144114402Sru delete pp; 5145114402Sru return this; 5146114402Sru} 5147114402Sru 5148114402Sruhyphen_list *hmotion_node::get_hyphen_list(hyphen_list *tail, int *) 5149114402Sru{ 5150114402Sru return new hyphen_list(0, tail); 5151114402Sru} 5152114402Sru 5153114402Sruint space_char_hmotion_node::same(node *nd) 5154114402Sru{ 5155114402Sru return n == ((space_char_hmotion_node *)nd)->n 5156114402Sru && col == ((space_char_hmotion_node *)nd)->col; 5157114402Sru} 5158114402Sru 5159114402Sruconst char *space_char_hmotion_node::type() 5160114402Sru{ 5161114402Sru return "space_char_hmotion_node"; 5162114402Sru} 5163114402Sru 5164114402Sruint space_char_hmotion_node::force_tprint() 5165114402Sru{ 5166114402Sru return 0; 5167114402Sru} 5168114402Sru 5169151497Sruint space_char_hmotion_node::is_tag() 5170114402Sru{ 5171151497Sru return 0; 5172151497Sru} 5173151497Sru 5174151497Srunode *space_char_hmotion_node::add_self(node *nd, hyphen_list **p) 5175151497Sru{ 5176151497Sru next = nd; 5177114402Sru hyphen_list *pp = *p; 5178114402Sru *p = (*p)->next; 5179114402Sru delete pp; 5180114402Sru return this; 5181114402Sru} 5182114402Sru 5183114402Sruhyphen_list *space_char_hmotion_node::get_hyphen_list(hyphen_list *tail, 5184114402Sru int *) 5185114402Sru{ 5186114402Sru return new hyphen_list(0, tail); 5187114402Sru} 5188114402Sru 5189114402Sruint vmotion_node::same(node *nd) 5190114402Sru{ 5191114402Sru return n == ((vmotion_node *)nd)->n 5192114402Sru && col == ((vmotion_node *)nd)->col; 5193114402Sru} 5194114402Sru 5195114402Sruconst char *vmotion_node::type() 5196114402Sru{ 5197114402Sru return "vmotion_node"; 5198114402Sru} 5199114402Sru 5200114402Sruint vmotion_node::force_tprint() 5201114402Sru{ 5202114402Sru return 0; 5203114402Sru} 5204114402Sru 5205151497Sruint vmotion_node::is_tag() 5206151497Sru{ 5207151497Sru return 0; 5208151497Sru} 5209151497Sru 5210114402Sruint hline_node::same(node *nd) 5211114402Sru{ 5212114402Sru return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n); 5213114402Sru} 5214114402Sru 5215114402Sruconst char *hline_node::type() 5216114402Sru{ 5217114402Sru return "hline_node"; 5218114402Sru} 5219114402Sru 5220114402Sruint hline_node::force_tprint() 5221114402Sru{ 5222114402Sru return 0; 5223114402Sru} 5224114402Sru 5225151497Sruint hline_node::is_tag() 5226151497Sru{ 5227151497Sru return 0; 5228151497Sru} 5229151497Sru 5230114402Sruint vline_node::same(node *nd) 5231114402Sru{ 5232114402Sru return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n); 5233114402Sru} 5234114402Sru 5235114402Sruconst char *vline_node::type() 5236114402Sru{ 5237114402Sru return "vline_node"; 5238114402Sru} 5239114402Sru 5240114402Sruint vline_node::force_tprint() 5241114402Sru{ 5242114402Sru return 0; 5243114402Sru} 5244114402Sru 5245151497Sruint vline_node::is_tag() 5246151497Sru{ 5247151497Sru return 0; 5248151497Sru} 5249151497Sru 5250114402Sruint dummy_node::same(node * /*nd*/) 5251114402Sru{ 5252114402Sru return 1; 5253114402Sru} 5254114402Sru 5255114402Sruconst char *dummy_node::type() 5256114402Sru{ 5257114402Sru return "dummy_node"; 5258114402Sru} 5259114402Sru 5260114402Sruint dummy_node::force_tprint() 5261114402Sru{ 5262114402Sru return 0; 5263114402Sru} 5264114402Sru 5265151497Sruint dummy_node::is_tag() 5266151497Sru{ 5267151497Sru return 0; 5268151497Sru} 5269151497Sru 5270114402Sruint transparent_dummy_node::same(node * /*nd*/) 5271114402Sru{ 5272114402Sru return 1; 5273114402Sru} 5274114402Sru 5275114402Sruconst char *transparent_dummy_node::type() 5276114402Sru{ 5277114402Sru return "transparent_dummy_node"; 5278114402Sru} 5279114402Sru 5280114402Sruint transparent_dummy_node::force_tprint() 5281114402Sru{ 5282114402Sru return 0; 5283114402Sru} 5284114402Sru 5285151497Sruint transparent_dummy_node::is_tag() 5286151497Sru{ 5287151497Sru return 0; 5288151497Sru} 5289151497Sru 5290114402Sruint transparent_dummy_node::ends_sentence() 5291114402Sru{ 5292114402Sru return 2; 5293114402Sru} 5294114402Sru 5295114402Sruint zero_width_node::same(node *nd) 5296114402Sru{ 5297114402Sru return same_node_list(n, ((zero_width_node *)nd)->n); 5298114402Sru} 5299114402Sru 5300114402Sruconst char *zero_width_node::type() 5301114402Sru{ 5302114402Sru return "zero_width_node"; 5303114402Sru} 5304114402Sru 5305114402Sruint zero_width_node::force_tprint() 5306114402Sru{ 5307114402Sru return 0; 5308114402Sru} 5309114402Sru 5310151497Sruint zero_width_node::is_tag() 5311151497Sru{ 5312151497Sru return 0; 5313151497Sru} 5314151497Sru 5315114402Sruint italic_corrected_node::same(node *nd) 5316114402Sru{ 5317114402Sru return (x == ((italic_corrected_node *)nd)->x 5318114402Sru && same_node(n, ((italic_corrected_node *)nd)->n)); 5319114402Sru} 5320114402Sru 5321114402Sruconst char *italic_corrected_node::type() 5322114402Sru{ 5323114402Sru return "italic_corrected_node"; 5324114402Sru} 5325114402Sru 5326114402Sruint italic_corrected_node::force_tprint() 5327114402Sru{ 5328114402Sru return 0; 5329114402Sru} 5330114402Sru 5331151497Sruint italic_corrected_node::is_tag() 5332114402Sru{ 5333151497Sru return 0; 5334114402Sru} 5335114402Sru 5336151497Sruleft_italic_corrected_node::left_italic_corrected_node(node *xx) 5337151497Sru: node(xx), n(0) 5338151497Sru{ 5339151497Sru} 5340151497Sru 5341151497Sruleft_italic_corrected_node::left_italic_corrected_node(statem *s, int pop, 5342151497Sru node *xx) 5343151497Sru: node(xx, s, pop), n(0) 5344151497Sru{ 5345151497Sru} 5346151497Sru 5347114402Sruleft_italic_corrected_node::~left_italic_corrected_node() 5348114402Sru{ 5349114402Sru delete n; 5350114402Sru} 5351114402Sru 5352114402Srunode *left_italic_corrected_node::merge_glyph_node(glyph_node *gn) 5353114402Sru{ 5354114402Sru if (n == 0) { 5355114402Sru hunits lic = gn->left_italic_correction(); 5356114402Sru if (!lic.is_zero()) { 5357114402Sru x = lic; 5358114402Sru n = gn; 5359114402Sru return this; 5360114402Sru } 5361114402Sru } 5362114402Sru else { 5363114402Sru node *nd = n->merge_glyph_node(gn); 5364114402Sru if (nd) { 5365114402Sru n = nd; 5366114402Sru x = n->left_italic_correction(); 5367114402Sru return this; 5368114402Sru } 5369114402Sru } 5370114402Sru return 0; 5371114402Sru} 5372114402Sru 5373114402Srunode *left_italic_corrected_node::copy() 5374114402Sru{ 5375151497Sru left_italic_corrected_node *nd = 5376151497Sru new left_italic_corrected_node(state, div_nest_level); 5377114402Sru if (n) { 5378114402Sru nd->n = n->copy(); 5379114402Sru nd->x = x; 5380114402Sru } 5381114402Sru return nd; 5382114402Sru} 5383114402Sru 5384114402Sruvoid left_italic_corrected_node::tprint(troff_output_file *out) 5385114402Sru{ 5386114402Sru if (n) { 5387114402Sru out->right(x); 5388114402Sru n->tprint(out); 5389114402Sru } 5390114402Sru} 5391114402Sru 5392114402Sruconst char *left_italic_corrected_node::type() 5393114402Sru{ 5394114402Sru return "left_italic_corrected_node"; 5395114402Sru} 5396114402Sru 5397114402Sruint left_italic_corrected_node::force_tprint() 5398114402Sru{ 5399114402Sru return 0; 5400114402Sru} 5401114402Sru 5402151497Sruint left_italic_corrected_node::is_tag() 5403151497Sru{ 5404151497Sru return 0; 5405151497Sru} 5406151497Sru 5407114402Sruint left_italic_corrected_node::same(node *nd) 5408114402Sru{ 5409114402Sru return (x == ((left_italic_corrected_node *)nd)->x 5410114402Sru && same_node(n, ((left_italic_corrected_node *)nd)->n)); 5411114402Sru} 5412114402Sru 5413114402Sruvoid left_italic_corrected_node::ascii_print(ascii_output_file *out) 5414114402Sru{ 5415114402Sru if (n) 5416114402Sru n->ascii_print(out); 5417114402Sru} 5418114402Sru 5419114402Sruhunits left_italic_corrected_node::width() 5420114402Sru{ 5421114402Sru return n ? n->width() + x : H0; 5422114402Sru} 5423114402Sru 5424151497Sruvoid left_italic_corrected_node::vertical_extent(vunits *minimum, 5425151497Sru vunits *maximum) 5426114402Sru{ 5427114402Sru if (n) 5428151497Sru n->vertical_extent(minimum, maximum); 5429114402Sru else 5430151497Sru node::vertical_extent(minimum, maximum); 5431114402Sru} 5432114402Sru 5433114402Sruhunits left_italic_corrected_node::skew() 5434114402Sru{ 5435114402Sru return n ? n->skew() + x/2 : H0; 5436114402Sru} 5437114402Sru 5438114402Sruhunits left_italic_corrected_node::subscript_correction() 5439114402Sru{ 5440114402Sru return n ? n->subscript_correction() : H0; 5441114402Sru} 5442114402Sru 5443114402Sruhunits left_italic_corrected_node::italic_correction() 5444114402Sru{ 5445114402Sru return n ? n->italic_correction() : H0; 5446114402Sru} 5447114402Sru 5448114402Sruint left_italic_corrected_node::ends_sentence() 5449114402Sru{ 5450114402Sru return n ? n->ends_sentence() : 0; 5451114402Sru} 5452114402Sru 5453114402Sruint left_italic_corrected_node::overlaps_horizontally() 5454114402Sru{ 5455114402Sru return n ? n->overlaps_horizontally() : 0; 5456114402Sru} 5457114402Sru 5458114402Sruint left_italic_corrected_node::overlaps_vertically() 5459114402Sru{ 5460114402Sru return n ? n->overlaps_vertically() : 0; 5461114402Sru} 5462114402Sru 5463114402Srunode *left_italic_corrected_node::last_char_node() 5464114402Sru{ 5465114402Sru return n ? n->last_char_node() : 0; 5466114402Sru} 5467114402Sru 5468114402Srutfont *left_italic_corrected_node::get_tfont() 5469114402Sru{ 5470114402Sru return n ? n->get_tfont() : 0; 5471114402Sru} 5472114402Sru 5473114402Sruhyphenation_type left_italic_corrected_node::get_hyphenation_type() 5474114402Sru{ 5475114402Sru if (n) 5476114402Sru return n->get_hyphenation_type(); 5477114402Sru else 5478114402Sru return HYPHEN_MIDDLE; 5479114402Sru} 5480114402Sru 5481114402Sruhyphen_list *left_italic_corrected_node::get_hyphen_list(hyphen_list *tail, 5482114402Sru int *count) 5483114402Sru{ 5484114402Sru return n ? n->get_hyphen_list(tail, count) : tail; 5485114402Sru} 5486114402Sru 5487114402Srunode *left_italic_corrected_node::add_self(node *nd, hyphen_list **p) 5488114402Sru{ 5489114402Sru if (n) { 5490151497Sru nd = new left_italic_corrected_node(state, div_nest_level, nd); 5491114402Sru nd = n->add_self(nd, p); 5492114402Sru n = 0; 5493114402Sru delete this; 5494114402Sru } 5495114402Sru return nd; 5496114402Sru} 5497114402Sru 5498114402Sruint left_italic_corrected_node::character_type() 5499114402Sru{ 5500114402Sru return n ? n->character_type() : 0; 5501114402Sru} 5502114402Sru 5503114402Sruint overstrike_node::same(node *nd) 5504114402Sru{ 5505114402Sru return same_node_list(list, ((overstrike_node *)nd)->list); 5506114402Sru} 5507114402Sru 5508114402Sruconst char *overstrike_node::type() 5509114402Sru{ 5510114402Sru return "overstrike_node"; 5511114402Sru} 5512114402Sru 5513114402Sruint overstrike_node::force_tprint() 5514114402Sru{ 5515114402Sru return 0; 5516114402Sru} 5517114402Sru 5518151497Sruint overstrike_node::is_tag() 5519151497Sru{ 5520151497Sru return 0; 5521151497Sru} 5522151497Sru 5523114402Srunode *overstrike_node::add_self(node *n, hyphen_list **p) 5524114402Sru{ 5525114402Sru next = n; 5526114402Sru hyphen_list *pp = *p; 5527114402Sru *p = (*p)->next; 5528114402Sru delete pp; 5529114402Sru return this; 5530114402Sru} 5531114402Sru 5532114402Sruhyphen_list *overstrike_node::get_hyphen_list(hyphen_list *tail, int *) 5533114402Sru{ 5534114402Sru return new hyphen_list(0, tail); 5535114402Sru} 5536114402Sru 5537114402Sruint bracket_node::same(node *nd) 5538114402Sru{ 5539114402Sru return same_node_list(list, ((bracket_node *)nd)->list); 5540114402Sru} 5541114402Sru 5542114402Sruconst char *bracket_node::type() 5543114402Sru{ 5544114402Sru return "bracket_node"; 5545114402Sru} 5546114402Sru 5547114402Sruint bracket_node::force_tprint() 5548114402Sru{ 5549114402Sru return 0; 5550114402Sru} 5551114402Sru 5552151497Sruint bracket_node::is_tag() 5553151497Sru{ 5554151497Sru return 0; 5555151497Sru} 5556151497Sru 5557114402Sruint composite_node::same(node *nd) 5558114402Sru{ 5559114402Sru return ci == ((composite_node *)nd)->ci 5560114402Sru && same_node_list(n, ((composite_node *)nd)->n); 5561114402Sru} 5562114402Sru 5563114402Sruconst char *composite_node::type() 5564114402Sru{ 5565114402Sru return "composite_node"; 5566114402Sru} 5567114402Sru 5568114402Sruint composite_node::force_tprint() 5569114402Sru{ 5570114402Sru return 0; 5571114402Sru} 5572114402Sru 5573151497Sruint composite_node::is_tag() 5574151497Sru{ 5575151497Sru return 0; 5576151497Sru} 5577151497Sru 5578114402Sruint glyph_node::same(node *nd) 5579114402Sru{ 5580114402Sru return ci == ((glyph_node *)nd)->ci 5581114402Sru && tf == ((glyph_node *)nd)->tf 5582114402Sru && gcol == ((glyph_node *)nd)->gcol 5583114402Sru && fcol == ((glyph_node *)nd)->fcol; 5584114402Sru} 5585114402Sru 5586114402Sruconst char *glyph_node::type() 5587114402Sru{ 5588114402Sru return "glyph_node"; 5589114402Sru} 5590114402Sru 5591114402Sruint glyph_node::force_tprint() 5592114402Sru{ 5593114402Sru return 0; 5594114402Sru} 5595114402Sru 5596151497Sruint glyph_node::is_tag() 5597151497Sru{ 5598151497Sru return 0; 5599151497Sru} 5600151497Sru 5601114402Sruint ligature_node::same(node *nd) 5602114402Sru{ 5603114402Sru return (same_node(n1, ((ligature_node *)nd)->n1) 5604114402Sru && same_node(n2, ((ligature_node *)nd)->n2) 5605114402Sru && glyph_node::same(nd)); 5606114402Sru} 5607114402Sru 5608114402Sruconst char *ligature_node::type() 5609114402Sru{ 5610114402Sru return "ligature_node"; 5611114402Sru} 5612114402Sru 5613114402Sruint ligature_node::force_tprint() 5614114402Sru{ 5615114402Sru return 0; 5616114402Sru} 5617114402Sru 5618151497Sruint ligature_node::is_tag() 5619151497Sru{ 5620151497Sru return 0; 5621151497Sru} 5622151497Sru 5623114402Sruint kern_pair_node::same(node *nd) 5624114402Sru{ 5625114402Sru return (amount == ((kern_pair_node *)nd)->amount 5626114402Sru && same_node(n1, ((kern_pair_node *)nd)->n1) 5627114402Sru && same_node(n2, ((kern_pair_node *)nd)->n2)); 5628114402Sru} 5629114402Sru 5630114402Sruconst char *kern_pair_node::type() 5631114402Sru{ 5632114402Sru return "kern_pair_node"; 5633114402Sru} 5634114402Sru 5635114402Sruint kern_pair_node::force_tprint() 5636114402Sru{ 5637114402Sru return 0; 5638114402Sru} 5639114402Sru 5640151497Sruint kern_pair_node::is_tag() 5641151497Sru{ 5642151497Sru return 0; 5643151497Sru} 5644151497Sru 5645114402Sruint dbreak_node::same(node *nd) 5646114402Sru{ 5647114402Sru return (same_node_list(none, ((dbreak_node *)nd)->none) 5648114402Sru && same_node_list(pre, ((dbreak_node *)nd)->pre) 5649114402Sru && same_node_list(post, ((dbreak_node *)nd)->post)); 5650114402Sru} 5651114402Sru 5652114402Sruconst char *dbreak_node::type() 5653114402Sru{ 5654114402Sru return "dbreak_node"; 5655114402Sru} 5656114402Sru 5657114402Sruint dbreak_node::force_tprint() 5658114402Sru{ 5659114402Sru return 0; 5660114402Sru} 5661114402Sru 5662151497Sruint dbreak_node::is_tag() 5663151497Sru{ 5664151497Sru return 0; 5665151497Sru} 5666151497Sru 5667114402Sruint break_char_node::same(node *nd) 5668114402Sru{ 5669114402Sru return break_code == ((break_char_node *)nd)->break_code 5670114402Sru && col == ((break_char_node *)nd)->col 5671114402Sru && same_node(ch, ((break_char_node *)nd)->ch); 5672114402Sru} 5673114402Sru 5674114402Sruconst char *break_char_node::type() 5675114402Sru{ 5676114402Sru return "break_char_node"; 5677114402Sru} 5678114402Sru 5679114402Sruint break_char_node::force_tprint() 5680114402Sru{ 5681114402Sru return 0; 5682114402Sru} 5683114402Sru 5684151497Sruint break_char_node::is_tag() 5685151497Sru{ 5686151497Sru return 0; 5687151497Sru} 5688151497Sru 5689114402Sruint line_start_node::same(node * /*nd*/) 5690114402Sru{ 5691114402Sru return 1; 5692114402Sru} 5693114402Sru 5694114402Sruconst char *line_start_node::type() 5695114402Sru{ 5696114402Sru return "line_start_node"; 5697114402Sru} 5698114402Sru 5699114402Sruint line_start_node::force_tprint() 5700114402Sru{ 5701114402Sru return 0; 5702114402Sru} 5703114402Sru 5704151497Sruint line_start_node::is_tag() 5705151497Sru{ 5706151497Sru return 0; 5707151497Sru} 5708151497Sru 5709114402Sruint space_node::same(node *nd) 5710114402Sru{ 5711114402Sru return n == ((space_node *)nd)->n 5712114402Sru && set == ((space_node *)nd)->set 5713114402Sru && col == ((space_node *)nd)->col; 5714114402Sru} 5715114402Sru 5716114402Sruconst char *space_node::type() 5717114402Sru{ 5718114402Sru return "space_node"; 5719114402Sru} 5720114402Sru 5721114402Sruint word_space_node::same(node *nd) 5722114402Sru{ 5723114402Sru return n == ((word_space_node *)nd)->n 5724114402Sru && set == ((word_space_node *)nd)->set 5725114402Sru && col == ((word_space_node *)nd)->col; 5726114402Sru} 5727114402Sru 5728114402Sruconst char *word_space_node::type() 5729114402Sru{ 5730114402Sru return "word_space_node"; 5731114402Sru} 5732114402Sru 5733114402Sruint word_space_node::force_tprint() 5734114402Sru{ 5735114402Sru return 0; 5736114402Sru} 5737114402Sru 5738151497Sruint word_space_node::is_tag() 5739151497Sru{ 5740151497Sru return 0; 5741151497Sru} 5742151497Sru 5743114402Sruvoid unbreakable_space_node::tprint(troff_output_file *out) 5744114402Sru{ 5745114402Sru out->fill_color(col); 5746114402Sru if (is_html) { 5747114402Sru // we emit the space width as a negative glyph index 5748114402Sru out->flush_tbuf(); 5749114402Sru out->do_motion(); 5750114402Sru out->put('N'); 5751114402Sru out->put(-n.to_units()); 5752114402Sru out->put('\n'); 5753114402Sru } 5754114402Sru out->right(n); 5755114402Sru} 5756114402Sru 5757114402Sruint unbreakable_space_node::same(node *nd) 5758114402Sru{ 5759114402Sru return n == ((unbreakable_space_node *)nd)->n 5760114402Sru && set == ((unbreakable_space_node *)nd)->set 5761114402Sru && col == ((unbreakable_space_node *)nd)->col; 5762114402Sru} 5763114402Sru 5764114402Sruconst char *unbreakable_space_node::type() 5765114402Sru{ 5766114402Sru return "unbreakable_space_node"; 5767114402Sru} 5768114402Sru 5769151497Srunode *unbreakable_space_node::add_self(node *nd, hyphen_list **p) 5770114402Sru{ 5771151497Sru next = nd; 5772114402Sru hyphen_list *pp = *p; 5773114402Sru *p = (*p)->next; 5774114402Sru delete pp; 5775114402Sru return this; 5776114402Sru} 5777114402Sru 5778114402Sruhyphen_list *unbreakable_space_node::get_hyphen_list(hyphen_list *tail, int *) 5779114402Sru{ 5780114402Sru return new hyphen_list(0, tail); 5781114402Sru} 5782114402Sru 5783114402Sruint diverted_space_node::same(node *nd) 5784114402Sru{ 5785114402Sru return n == ((diverted_space_node *)nd)->n; 5786114402Sru} 5787114402Sru 5788114402Sruconst char *diverted_space_node::type() 5789114402Sru{ 5790114402Sru return "diverted_space_node"; 5791114402Sru} 5792114402Sru 5793114402Sruint diverted_space_node::force_tprint() 5794114402Sru{ 5795114402Sru return 0; 5796114402Sru} 5797114402Sru 5798151497Sruint diverted_space_node::is_tag() 5799151497Sru{ 5800151497Sru return 0; 5801151497Sru} 5802151497Sru 5803114402Sruint diverted_copy_file_node::same(node *nd) 5804114402Sru{ 5805114402Sru return filename == ((diverted_copy_file_node *)nd)->filename; 5806114402Sru} 5807114402Sru 5808114402Sruconst char *diverted_copy_file_node::type() 5809114402Sru{ 5810114402Sru return "diverted_copy_file_node"; 5811114402Sru} 5812114402Sru 5813114402Sruint diverted_copy_file_node::force_tprint() 5814114402Sru{ 5815114402Sru return 0; 5816114402Sru} 5817114402Sru 5818151497Sruint diverted_copy_file_node::is_tag() 5819151497Sru{ 5820151497Sru return 0; 5821151497Sru} 5822151497Sru 5823114402Sru// Grow the font_table so that its size is > n. 5824114402Sru 5825114402Srustatic void grow_font_table(int n) 5826114402Sru{ 5827114402Sru assert(n >= font_table_size); 5828114402Sru font_info **old_font_table = font_table; 5829114402Sru int old_font_table_size = font_table_size; 5830114402Sru font_table_size = font_table_size ? (font_table_size*3)/2 : 10; 5831114402Sru if (font_table_size <= n) 5832114402Sru font_table_size = n + 10; 5833114402Sru font_table = new font_info *[font_table_size]; 5834114402Sru if (old_font_table_size) 5835114402Sru memcpy(font_table, old_font_table, 5836114402Sru old_font_table_size*sizeof(font_info *)); 5837114402Sru a_delete old_font_table; 5838114402Sru for (int i = old_font_table_size; i < font_table_size; i++) 5839114402Sru font_table[i] = 0; 5840114402Sru} 5841114402Sru 5842114402Srudictionary font_translation_dictionary(17); 5843114402Sru 5844114402Srustatic symbol get_font_translation(symbol nm) 5845114402Sru{ 5846114402Sru void *p = font_translation_dictionary.lookup(nm); 5847114402Sru return p ? symbol((char *)p) : nm; 5848114402Sru} 5849114402Sru 5850114402Srudictionary font_dictionary(50); 5851114402Sru 5852151497Srustatic int mount_font_no_translate(int n, symbol name, symbol external_name, 5853151497Sru int check_only = 0) 5854114402Sru{ 5855114402Sru assert(n >= 0); 5856114402Sru // We store the address of this char in font_dictionary to indicate 5857114402Sru // that we've previously tried to mount the font and failed. 5858114402Sru static char a_char; 5859114402Sru font *fm = 0; 5860114402Sru void *p = font_dictionary.lookup(external_name); 5861114402Sru if (p == 0) { 5862114402Sru int not_found; 5863151497Sru fm = font::load_font(external_name.contents(), ¬_found, check_only); 5864151497Sru if (check_only) 5865151497Sru return fm != 0; 5866114402Sru if (!fm) { 5867114402Sru if (not_found) 5868114402Sru warning(WARN_FONT, "can't find font `%1'", external_name.contents()); 5869114402Sru (void)font_dictionary.lookup(external_name, &a_char); 5870114402Sru return 0; 5871114402Sru } 5872114402Sru (void)font_dictionary.lookup(name, fm); 5873114402Sru } 5874114402Sru else if (p == &a_char) { 5875114402Sru#if 0 5876114402Sru error("invalid font `%1'", external_name.contents()); 5877114402Sru#endif 5878114402Sru return 0; 5879114402Sru } 5880114402Sru else 5881114402Sru fm = (font*)p; 5882151497Sru if (check_only) 5883151497Sru return 1; 5884114402Sru if (n >= font_table_size) { 5885114402Sru if (n - font_table_size > 1000) { 5886114402Sru error("font position too much larger than first unused position"); 5887114402Sru return 0; 5888114402Sru } 5889114402Sru grow_font_table(n); 5890114402Sru } 5891114402Sru else if (font_table[n] != 0) 5892114402Sru delete font_table[n]; 5893114402Sru font_table[n] = new font_info(name, n, external_name, fm); 5894114402Sru font_family::invalidate_fontno(n); 5895114402Sru return 1; 5896114402Sru} 5897114402Sru 5898114402Sruint mount_font(int n, symbol name, symbol external_name) 5899114402Sru{ 5900114402Sru assert(n >= 0); 5901114402Sru name = get_font_translation(name); 5902114402Sru if (external_name.is_null()) 5903114402Sru external_name = name; 5904114402Sru else 5905114402Sru external_name = get_font_translation(external_name); 5906114402Sru return mount_font_no_translate(n, name, external_name); 5907114402Sru} 5908114402Sru 5909151497Sruint check_font(symbol fam, symbol name) 5910151497Sru{ 5911151497Sru if (check_style(name)) 5912151497Sru name = concat(fam, name); 5913151497Sru return mount_font_no_translate(0, name, name, 1); 5914151497Sru} 5915151497Sru 5916151497Sruint check_style(symbol s) 5917151497Sru{ 5918151497Sru int i = symbol_fontno(s); 5919151497Sru return i < 0 ? 0 : font_table[i]->is_style(); 5920151497Sru} 5921151497Sru 5922114402Sruvoid mount_style(int n, symbol name) 5923114402Sru{ 5924114402Sru assert(n >= 0); 5925114402Sru if (n >= font_table_size) { 5926114402Sru if (n - font_table_size > 1000) { 5927114402Sru error("font position too much larger than first unused position"); 5928114402Sru return; 5929114402Sru } 5930114402Sru grow_font_table(n); 5931114402Sru } 5932114402Sru else if (font_table[n] != 0) 5933114402Sru delete font_table[n]; 5934114402Sru font_table[n] = new font_info(get_font_translation(name), n, NULL_SYMBOL, 0); 5935114402Sru font_family::invalidate_fontno(n); 5936114402Sru} 5937114402Sru 5938114402Sru/* global functions */ 5939114402Sru 5940114402Sruvoid font_translate() 5941114402Sru{ 5942114402Sru symbol from = get_name(1); 5943114402Sru if (!from.is_null()) { 5944114402Sru symbol to = get_name(); 5945114402Sru if (to.is_null() || from == to) 5946114402Sru font_translation_dictionary.remove(from); 5947114402Sru else 5948114402Sru (void)font_translation_dictionary.lookup(from, (void *)to.contents()); 5949114402Sru } 5950114402Sru skip_line(); 5951114402Sru} 5952114402Sru 5953114402Sruvoid font_position() 5954114402Sru{ 5955114402Sru int n; 5956114402Sru if (get_integer(&n)) { 5957114402Sru if (n < 0) 5958114402Sru error("negative font position"); 5959114402Sru else { 5960114402Sru symbol internal_name = get_name(1); 5961114402Sru if (!internal_name.is_null()) { 5962114402Sru symbol external_name = get_long_name(); 5963114402Sru mount_font(n, internal_name, external_name); // ignore error 5964114402Sru } 5965114402Sru } 5966114402Sru } 5967114402Sru skip_line(); 5968114402Sru} 5969114402Sru 5970114402Srufont_family::font_family(symbol s) 5971114402Sru: map_size(10), nm(s) 5972114402Sru{ 5973114402Sru map = new int[map_size]; 5974114402Sru for (int i = 0; i < map_size; i++) 5975114402Sru map[i] = -1; 5976114402Sru} 5977114402Sru 5978114402Srufont_family::~font_family() 5979114402Sru{ 5980114402Sru a_delete map; 5981114402Sru} 5982114402Sru 5983114402Sruint font_family::make_definite(int i) 5984114402Sru{ 5985114402Sru if (i >= 0) { 5986114402Sru if (i < map_size && map[i] >= 0) 5987114402Sru return map[i]; 5988114402Sru else { 5989114402Sru if (i < font_table_size && font_table[i] != 0) { 5990114402Sru if (i >= map_size) { 5991114402Sru int old_map_size = map_size; 5992114402Sru int *old_map = map; 5993114402Sru map_size *= 3; 5994114402Sru map_size /= 2; 5995114402Sru if (i >= map_size) 5996114402Sru map_size = i + 10; 5997114402Sru map = new int[map_size]; 5998114402Sru memcpy(map, old_map, old_map_size*sizeof(int)); 5999114402Sru a_delete old_map; 6000114402Sru for (int j = old_map_size; j < map_size; j++) 6001114402Sru map[j] = -1; 6002114402Sru } 6003114402Sru if (font_table[i]->is_style()) { 6004114402Sru symbol sty = font_table[i]->get_name(); 6005114402Sru symbol f = concat(nm, sty); 6006114402Sru int n; 6007114402Sru // don't use symbol_fontno, because that might return a style 6008114402Sru // and because we don't want to translate the name 6009114402Sru for (n = 0; n < font_table_size; n++) 6010114402Sru if (font_table[n] != 0 && font_table[n]->is_named(f) 6011114402Sru && !font_table[n]->is_style()) 6012114402Sru break; 6013114402Sru if (n >= font_table_size) { 6014114402Sru n = next_available_font_position(); 6015114402Sru if (!mount_font_no_translate(n, f, f)) 6016114402Sru return -1; 6017114402Sru } 6018114402Sru return map[i] = n; 6019114402Sru } 6020114402Sru else 6021114402Sru return map[i] = i; 6022114402Sru } 6023114402Sru else 6024114402Sru return -1; 6025114402Sru } 6026114402Sru } 6027114402Sru else 6028114402Sru return -1; 6029114402Sru} 6030114402Sru 6031114402Srudictionary family_dictionary(5); 6032114402Sru 6033114402Srufont_family *lookup_family(symbol nm) 6034114402Sru{ 6035114402Sru font_family *f = (font_family *)family_dictionary.lookup(nm); 6036114402Sru if (!f) { 6037114402Sru f = new font_family(nm); 6038114402Sru (void)family_dictionary.lookup(nm, f); 6039114402Sru } 6040114402Sru return f; 6041114402Sru} 6042114402Sru 6043114402Sruvoid font_family::invalidate_fontno(int n) 6044114402Sru{ 6045114402Sru assert(n >= 0 && n < font_table_size); 6046114402Sru dictionary_iterator iter(family_dictionary); 6047151497Sru symbol nam; 6048114402Sru font_family *fam; 6049151497Sru while (iter.get(&nam, (void **)&fam)) { 6050151497Sru int mapsize = fam->map_size; 6051151497Sru if (n < mapsize) 6052114402Sru fam->map[n] = -1; 6053151497Sru for (int i = 0; i < mapsize; i++) 6054114402Sru if (fam->map[i] == n) 6055114402Sru fam->map[i] = -1; 6056114402Sru } 6057114402Sru} 6058114402Sru 6059114402Sruvoid style() 6060114402Sru{ 6061114402Sru int n; 6062114402Sru if (get_integer(&n)) { 6063114402Sru if (n < 0) 6064114402Sru error("negative font position"); 6065114402Sru else { 6066114402Sru symbol internal_name = get_name(1); 6067114402Sru if (!internal_name.is_null()) 6068114402Sru mount_style(n, internal_name); 6069114402Sru } 6070114402Sru } 6071114402Sru skip_line(); 6072114402Sru} 6073114402Sru 6074114402Srustatic int get_fontno() 6075114402Sru{ 6076114402Sru int n; 6077114402Sru tok.skip(); 6078114402Sru if (tok.delimiter()) { 6079114402Sru symbol s = get_name(1); 6080114402Sru if (!s.is_null()) { 6081114402Sru n = symbol_fontno(s); 6082114402Sru if (n < 0) { 6083114402Sru n = next_available_font_position(); 6084114402Sru if (!mount_font(n, s)) 6085114402Sru return -1; 6086114402Sru } 6087114402Sru return curenv->get_family()->make_definite(n); 6088114402Sru } 6089114402Sru } 6090114402Sru else if (get_integer(&n)) { 6091114402Sru if (n < 0 || n >= font_table_size || font_table[n] == 0) 6092114402Sru error("bad font number"); 6093114402Sru else 6094114402Sru return curenv->get_family()->make_definite(n); 6095114402Sru } 6096114402Sru return -1; 6097114402Sru} 6098114402Sru 6099114402Srustatic int underline_fontno = 2; 6100114402Sru 6101114402Sruvoid underline_font() 6102114402Sru{ 6103114402Sru int n = get_fontno(); 6104114402Sru if (n >= 0) 6105114402Sru underline_fontno = n; 6106114402Sru skip_line(); 6107114402Sru} 6108114402Sru 6109114402Sruint get_underline_fontno() 6110114402Sru{ 6111114402Sru return underline_fontno; 6112114402Sru} 6113114402Sru 6114114402Sruvoid define_font_special_character() 6115114402Sru{ 6116114402Sru int n = get_fontno(); 6117114402Sru if (n < 0) { 6118114402Sru skip_line(); 6119114402Sru return; 6120114402Sru } 6121114402Sru symbol f = font_table[n]->get_name(); 6122114402Sru do_define_character(CHAR_FONT_SPECIAL, f.contents()); 6123114402Sru} 6124114402Sru 6125114402Sruvoid remove_font_special_character() 6126114402Sru{ 6127114402Sru int n = get_fontno(); 6128114402Sru if (n < 0) { 6129114402Sru skip_line(); 6130114402Sru return; 6131114402Sru } 6132114402Sru symbol f = font_table[n]->get_name(); 6133114402Sru while (!tok.newline() && !tok.eof()) { 6134114402Sru if (!tok.space() && !tok.tab()) { 6135114402Sru charinfo *s = tok.get_char(1); 6136114402Sru string gl(f.contents()); 6137114402Sru gl += ' '; 6138114402Sru gl += s->nm.contents(); 6139114402Sru gl += '\0'; 6140114402Sru charinfo *ci = get_charinfo(symbol(gl.contents())); 6141114402Sru if (!ci) 6142114402Sru break; 6143114402Sru macro *m = ci->set_macro(0); 6144114402Sru if (m) 6145114402Sru delete m; 6146114402Sru } 6147114402Sru tok.next(); 6148114402Sru } 6149114402Sru skip_line(); 6150114402Sru} 6151114402Sru 6152114402Srustatic void read_special_fonts(special_font_list **sp) 6153114402Sru{ 6154114402Sru special_font_list *s = *sp; 6155114402Sru *sp = 0; 6156114402Sru while (s != 0) { 6157114402Sru special_font_list *tem = s; 6158114402Sru s = s->next; 6159114402Sru delete tem; 6160114402Sru } 6161114402Sru special_font_list **p = sp; 6162114402Sru while (has_arg()) { 6163114402Sru int i = get_fontno(); 6164114402Sru if (i >= 0) { 6165114402Sru special_font_list *tem = new special_font_list; 6166114402Sru tem->n = i; 6167114402Sru tem->next = 0; 6168114402Sru *p = tem; 6169114402Sru p = &(tem->next); 6170114402Sru } 6171114402Sru } 6172114402Sru} 6173114402Sru 6174114402Sruvoid font_special_request() 6175114402Sru{ 6176114402Sru int n = get_fontno(); 6177114402Sru if (n >= 0) 6178114402Sru read_special_fonts(&font_table[n]->sf); 6179114402Sru skip_line(); 6180114402Sru} 6181114402Sru 6182114402Sruvoid special_request() 6183114402Sru{ 6184114402Sru read_special_fonts(&global_special_fonts); 6185114402Sru skip_line(); 6186114402Sru} 6187114402Sru 6188114402Sruint next_available_font_position() 6189114402Sru{ 6190114402Sru int i; 6191114402Sru for (i = 1; i < font_table_size && font_table[i] != 0; i++) 6192114402Sru ; 6193114402Sru return i; 6194114402Sru} 6195114402Sru 6196114402Sruint symbol_fontno(symbol s) 6197114402Sru{ 6198114402Sru s = get_font_translation(s); 6199114402Sru for (int i = 0; i < font_table_size; i++) 6200114402Sru if (font_table[i] != 0 && font_table[i]->is_named(s)) 6201114402Sru return i; 6202114402Sru return -1; 6203114402Sru} 6204114402Sru 6205114402Sruint is_good_fontno(int n) 6206114402Sru{ 6207114402Sru return n >= 0 && n < font_table_size && font_table[n] != 0; 6208114402Sru} 6209114402Sru 6210114402Sruint get_bold_fontno(int n) 6211114402Sru{ 6212114402Sru if (n >= 0 && n < font_table_size && font_table[n] != 0) { 6213114402Sru hunits offset; 6214114402Sru if (font_table[n]->get_bold(&offset)) 6215114402Sru return offset.to_units() + 1; 6216114402Sru else 6217114402Sru return 0; 6218114402Sru } 6219114402Sru else 6220114402Sru return 0; 6221114402Sru} 6222114402Sru 6223114402Sruhunits env_digit_width(environment *env) 6224114402Sru{ 6225114402Sru node *n = make_glyph_node(charset_table['0'], env); 6226114402Sru if (n) { 6227114402Sru hunits x = n->width(); 6228114402Sru delete n; 6229114402Sru return x; 6230114402Sru } 6231114402Sru else 6232114402Sru return H0; 6233114402Sru} 6234114402Sru 6235114402Sruhunits env_space_width(environment *env) 6236114402Sru{ 6237114402Sru int fn = env_definite_font(env); 6238114402Sru font_size fs = env->get_font_size(); 6239114402Sru if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) 6240114402Sru return scale(fs.to_units()/3, env->get_space_size(), 12); 6241114402Sru else 6242114402Sru return font_table[fn]->get_space_width(fs, env->get_space_size()); 6243114402Sru} 6244114402Sru 6245114402Sruhunits env_sentence_space_width(environment *env) 6246114402Sru{ 6247114402Sru int fn = env_definite_font(env); 6248114402Sru font_size fs = env->get_font_size(); 6249114402Sru if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) 6250114402Sru return scale(fs.to_units()/3, env->get_sentence_space_size(), 12); 6251114402Sru else 6252114402Sru return font_table[fn]->get_space_width(fs, env->get_sentence_space_size()); 6253114402Sru} 6254114402Sru 6255114402Sruhunits env_half_narrow_space_width(environment *env) 6256114402Sru{ 6257114402Sru int fn = env_definite_font(env); 6258114402Sru font_size fs = env->get_font_size(); 6259114402Sru if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) 6260114402Sru return 0; 6261114402Sru else 6262114402Sru return font_table[fn]->get_half_narrow_space_width(fs); 6263114402Sru} 6264114402Sru 6265114402Sruhunits env_narrow_space_width(environment *env) 6266114402Sru{ 6267114402Sru int fn = env_definite_font(env); 6268114402Sru font_size fs = env->get_font_size(); 6269114402Sru if (fn < 0 || fn >= font_table_size || font_table[fn] == 0) 6270114402Sru return 0; 6271114402Sru else 6272114402Sru return font_table[fn]->get_narrow_space_width(fs); 6273114402Sru} 6274114402Sru 6275114402Sruvoid bold_font() 6276114402Sru{ 6277114402Sru int n = get_fontno(); 6278114402Sru if (n >= 0) { 6279114402Sru if (has_arg()) { 6280114402Sru if (tok.delimiter()) { 6281114402Sru int f = get_fontno(); 6282114402Sru if (f >= 0) { 6283114402Sru units offset; 6284114402Sru if (has_arg() && get_number(&offset, 'u') && offset >= 1) 6285114402Sru font_table[f]->set_conditional_bold(n, hunits(offset - 1)); 6286114402Sru else 6287114402Sru font_table[f]->conditional_unbold(n); 6288114402Sru } 6289114402Sru } 6290114402Sru else { 6291114402Sru units offset; 6292114402Sru if (get_number(&offset, 'u') && offset >= 1) 6293114402Sru font_table[n]->set_bold(hunits(offset - 1)); 6294114402Sru else 6295114402Sru font_table[n]->unbold(); 6296114402Sru } 6297114402Sru } 6298114402Sru else 6299114402Sru font_table[n]->unbold(); 6300114402Sru } 6301114402Sru skip_line(); 6302114402Sru} 6303114402Sru 6304114402Srutrack_kerning_function::track_kerning_function() : non_zero(0) 6305114402Sru{ 6306114402Sru} 6307114402Sru 6308114402Srutrack_kerning_function::track_kerning_function(int min_s, hunits min_a, 6309114402Sru int max_s, hunits max_a) 6310114402Sru: non_zero(1), min_size(min_s), min_amount(min_a), max_size(max_s), 6311114402Sru max_amount(max_a) 6312114402Sru{ 6313114402Sru} 6314114402Sru 6315114402Sruint track_kerning_function::operator==(const track_kerning_function &tk) 6316114402Sru{ 6317114402Sru if (non_zero) 6318114402Sru return (tk.non_zero 6319114402Sru && min_size == tk.min_size 6320114402Sru && min_amount == tk.min_amount 6321114402Sru && max_size == tk.max_size 6322114402Sru && max_amount == tk.max_amount); 6323114402Sru else 6324114402Sru return !tk.non_zero; 6325114402Sru} 6326114402Sru 6327114402Sruint track_kerning_function::operator!=(const track_kerning_function &tk) 6328114402Sru{ 6329114402Sru if (non_zero) 6330114402Sru return (!tk.non_zero 6331114402Sru || min_size != tk.min_size 6332114402Sru || min_amount != tk.min_amount 6333114402Sru || max_size != tk.max_size 6334114402Sru || max_amount != tk.max_amount); 6335114402Sru else 6336114402Sru return tk.non_zero; 6337114402Sru} 6338114402Sru 6339114402Sruhunits track_kerning_function::compute(int size) 6340114402Sru{ 6341114402Sru if (non_zero) { 6342114402Sru if (max_size <= min_size) 6343114402Sru return min_amount; 6344114402Sru else if (size <= min_size) 6345114402Sru return min_amount; 6346114402Sru else if (size >= max_size) 6347114402Sru return max_amount; 6348114402Sru else 6349114402Sru return (scale(max_amount, size - min_size, max_size - min_size) 6350114402Sru + scale(min_amount, max_size - size, max_size - min_size)); 6351114402Sru } 6352114402Sru else 6353114402Sru return H0; 6354114402Sru} 6355114402Sru 6356114402Sruvoid track_kern() 6357114402Sru{ 6358114402Sru int n = get_fontno(); 6359114402Sru if (n >= 0) { 6360114402Sru int min_s, max_s; 6361114402Sru hunits min_a, max_a; 6362114402Sru if (has_arg() 6363114402Sru && get_number(&min_s, 'z') 6364114402Sru && get_hunits(&min_a, 'p') 6365114402Sru && get_number(&max_s, 'z') 6366114402Sru && get_hunits(&max_a, 'p')) { 6367114402Sru track_kerning_function tk(min_s, min_a, max_s, max_a); 6368114402Sru font_table[n]->set_track_kern(tk); 6369114402Sru } 6370114402Sru else { 6371114402Sru track_kerning_function tk; 6372114402Sru font_table[n]->set_track_kern(tk); 6373114402Sru } 6374114402Sru } 6375114402Sru skip_line(); 6376114402Sru} 6377114402Sru 6378114402Sruvoid constant_space() 6379114402Sru{ 6380114402Sru int n = get_fontno(); 6381114402Sru if (n >= 0) { 6382114402Sru int x, y; 6383114402Sru if (!has_arg() || !get_integer(&x)) 6384114402Sru font_table[n]->set_constant_space(CONSTANT_SPACE_NONE); 6385114402Sru else { 6386114402Sru if (!has_arg() || !get_number(&y, 'z')) 6387114402Sru font_table[n]->set_constant_space(CONSTANT_SPACE_RELATIVE, x); 6388114402Sru else 6389114402Sru font_table[n]->set_constant_space(CONSTANT_SPACE_ABSOLUTE, 6390114402Sru scale(y*x, 6391114402Sru units_per_inch, 6392114402Sru 36*72*sizescale)); 6393114402Sru } 6394114402Sru } 6395114402Sru skip_line(); 6396114402Sru} 6397114402Sru 6398114402Sruvoid ligature() 6399114402Sru{ 6400114402Sru int lig; 6401114402Sru if (has_arg() && get_integer(&lig) && lig >= 0 && lig <= 2) 6402114402Sru global_ligature_mode = lig; 6403114402Sru else 6404114402Sru global_ligature_mode = 1; 6405114402Sru skip_line(); 6406114402Sru} 6407114402Sru 6408114402Sruvoid kern_request() 6409114402Sru{ 6410114402Sru int k; 6411114402Sru if (has_arg() && get_integer(&k)) 6412114402Sru global_kern_mode = k != 0; 6413114402Sru else 6414114402Sru global_kern_mode = 1; 6415114402Sru skip_line(); 6416114402Sru} 6417114402Sru 6418114402Sruvoid set_soft_hyphen_char() 6419114402Sru{ 6420114402Sru soft_hyphen_char = get_optional_char(); 6421114402Sru if (!soft_hyphen_char) 6422114402Sru soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL); 6423114402Sru skip_line(); 6424114402Sru} 6425114402Sru 6426114402Sruvoid init_output() 6427114402Sru{ 6428114402Sru if (suppress_output_flag) 6429114402Sru the_output = new suppress_output_file; 6430114402Sru else if (ascii_output_flag) 6431114402Sru the_output = new ascii_output_file; 6432114402Sru else 6433114402Sru the_output = new troff_output_file; 6434114402Sru} 6435114402Sru 6436114402Sruclass next_available_font_position_reg : public reg { 6437114402Srupublic: 6438114402Sru const char *get_string(); 6439114402Sru}; 6440114402Sru 6441114402Sruconst char *next_available_font_position_reg::get_string() 6442114402Sru{ 6443114402Sru return i_to_a(next_available_font_position()); 6444114402Sru} 6445114402Sru 6446114402Sruclass printing_reg : public reg { 6447114402Srupublic: 6448114402Sru const char *get_string(); 6449114402Sru}; 6450114402Sru 6451114402Sruconst char *printing_reg::get_string() 6452114402Sru{ 6453114402Sru if (the_output) 6454114402Sru return the_output->is_printing() ? "1" : "0"; 6455114402Sru else 6456114402Sru return "0"; 6457114402Sru} 6458114402Sru 6459114402Sruvoid init_node_requests() 6460114402Sru{ 6461114402Sru init_request("bd", bold_font); 6462114402Sru init_request("cs", constant_space); 6463114402Sru init_request("fp", font_position); 6464114402Sru init_request("fschar", define_font_special_character); 6465114402Sru init_request("fspecial", font_special_request); 6466114402Sru init_request("ftr", font_translate); 6467114402Sru init_request("kern", kern_request); 6468114402Sru init_request("lg", ligature); 6469114402Sru init_request("rfschar", remove_font_special_character); 6470114402Sru init_request("shc", set_soft_hyphen_char); 6471114402Sru init_request("special", special_request); 6472114402Sru init_request("sty", style); 6473114402Sru init_request("tkf", track_kern); 6474114402Sru init_request("uf", underline_font); 6475114402Sru number_reg_dictionary.define(".fp", new next_available_font_position_reg); 6476114402Sru number_reg_dictionary.define(".kern", 6477114402Sru new constant_int_reg(&global_kern_mode)); 6478114402Sru number_reg_dictionary.define(".lg", 6479114402Sru new constant_int_reg(&global_ligature_mode)); 6480114402Sru number_reg_dictionary.define(".P", new printing_reg); 6481114402Sru soft_hyphen_char = get_charinfo(HYPHEN_SYMBOL); 6482114402Sru} 6483