1// -*- C++ -*- 2/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 3 Free Software Foundation, Inc. 4 Written by James Clark (jjc@jclark.com) 5 6This file is part of groff. 7 8groff is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13groff is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License along 19with groff; see the file COPYING. If not, write to the Free Software 20Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 21 22struct hyphen_list { 23 unsigned char hyphen; 24 unsigned char breakable; 25 unsigned char hyphenation_code; 26 hyphen_list *next; 27 hyphen_list(unsigned char code, hyphen_list *p = 0); 28}; 29 30void hyphenate(hyphen_list *, unsigned); 31 32enum hyphenation_type { HYPHEN_MIDDLE, HYPHEN_BOUNDARY, HYPHEN_INHIBIT }; 33 34class ascii_output_file; 35 36struct breakpoint; 37struct vertical_size; 38class charinfo; 39 40class macro; 41 42class troff_output_file; 43class tfont; 44class environment; 45 46class glyph_node; 47class diverted_space_node; 48class token_node; 49 50struct node { 51 node *next; 52 node *last; 53 statem *state; 54 statem *push_state; 55 int div_nest_level; 56 int is_special; 57 node(); 58 node(node *); 59 node(node *, statem *, int); 60 node *add_char(charinfo *, environment *, hunits *, int *, node ** = 0); 61 62 virtual ~node(); 63 virtual node *copy() = 0; 64 virtual int set_unformat_flag(); 65 virtual int force_tprint() = 0; 66 virtual int is_tag() = 0; 67 virtual hunits width(); 68 virtual hunits subscript_correction(); 69 virtual hunits italic_correction(); 70 virtual hunits left_italic_correction(); 71 virtual hunits skew(); 72 virtual int nspaces(); 73 virtual int merge_space(hunits, hunits, hunits); 74 virtual vunits vertical_width(); 75 virtual node *last_char_node(); 76 virtual void vertical_extent(vunits *, vunits *); 77 virtual int character_type(); 78 virtual void set_vertical_size(vertical_size *); 79 virtual int ends_sentence(); 80 virtual node *merge_self(node *); 81 virtual node *add_discretionary_hyphen(); 82 virtual node *add_self(node *, hyphen_list **); 83 virtual hyphen_list *get_hyphen_list(hyphen_list *, int *); 84 virtual void ascii_print(ascii_output_file *); 85 virtual void asciify(macro *); 86 virtual int discardable(); 87 virtual void spread_space(int *, hunits *); 88 virtual void freeze_space(); 89 virtual void is_escape_colon(); 90 virtual breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); 91 virtual int nbreaks(); 92 virtual void split(int, node **, node **); 93 virtual hyphenation_type get_hyphenation_type(); 94 virtual int reread(int *); 95 virtual token_node *get_token_node(); 96 virtual int overlaps_vertically(); 97 virtual int overlaps_horizontally(); 98 virtual units size(); 99 virtual int interpret(macro *); 100 101 virtual node *merge_glyph_node(glyph_node *); 102 virtual tfont *get_tfont(); 103 virtual color *get_glyph_color(); 104 virtual color *get_fill_color(); 105 virtual void tprint(troff_output_file *); 106 virtual void zero_width_tprint(troff_output_file *); 107 108 node *add_italic_correction(hunits *); 109 110 virtual int same(node *) = 0; 111 virtual const char *type() = 0; 112 virtual void debug_node(); 113 virtual void debug_node_list(); 114}; 115 116inline node::node() 117: next(0), last(0), state(0), push_state(0), div_nest_level(0), is_special(0) 118{ 119} 120 121inline node::node(node *n) 122: next(n), last(0), state(0), push_state(0), div_nest_level(0), is_special(0) 123{ 124} 125 126inline node::node(node *n, statem *s, int divlevel) 127: next(n), last(0), push_state(0), div_nest_level(divlevel), is_special(0) 128{ 129 if (s) 130 state = new statem(s); 131 else 132 state = 0; 133} 134 135inline node::~node() 136{ 137} 138 139// 0 means it doesn't, 1 means it does, 2 means it's transparent 140 141int node_list_ends_sentence(node *); 142 143struct breakpoint { 144 breakpoint *next; 145 hunits width; 146 int nspaces; 147 node *nd; 148 int index; 149 char hyphenated; 150}; 151 152class line_start_node : public node { 153public: 154 line_start_node() {} 155 node *copy() { return new line_start_node; } 156 int same(node *); 157 int force_tprint(); 158 int is_tag(); 159 const char *type(); 160 void asciify(macro *); 161}; 162 163class space_node : public node { 164private: 165#if 0 166 enum { BLOCK = 1024 }; 167 static space_node *free_list; 168 void operator delete(void *); 169#endif 170protected: 171 hunits n; 172 char set; 173 char was_escape_colon; 174 color *col; /* for grotty */ 175 space_node(hunits, int, int, color *, statem *, int, node * = 0); 176public: 177 space_node(hunits, color *, statem *, int, node * = 0); 178 space_node(hunits, color *, node * = 0); 179#if 0 180 ~space_node(); 181 void *operator new(size_t); 182#endif 183 node *copy(); 184 int nspaces(); 185 hunits width(); 186 int discardable(); 187 int merge_space(hunits, hunits, hunits); 188 void freeze_space(); 189 void is_escape_colon(); 190 void spread_space(int *, hunits *); 191 void tprint(troff_output_file *); 192 breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); 193 int nbreaks(); 194 void split(int, node **, node **); 195 void ascii_print(ascii_output_file *); 196 int same(node *); 197 void asciify(macro *); 198 const char *type(); 199 int force_tprint(); 200 int is_tag(); 201 hyphenation_type get_hyphenation_type(); 202}; 203 204struct width_list { 205 hunits width; 206 hunits sentence_width; 207 width_list *next; 208 width_list(hunits, hunits); 209 width_list(width_list *); 210}; 211 212class word_space_node : public space_node { 213protected: 214 width_list *orig_width; 215 unsigned char unformat; 216 word_space_node(hunits, int, color *, width_list *, int, statem *, int, 217 node * = 0); 218public: 219 word_space_node(hunits, color *, width_list *, node * = 0); 220 ~word_space_node(); 221 node *copy(); 222 int reread(int *); 223 int set_unformat_flag(); 224 void tprint(troff_output_file *); 225 int same(node *); 226 void asciify(macro *); 227 const char *type(); 228 int merge_space(hunits, hunits, hunits); 229 int force_tprint(); 230 int is_tag(); 231}; 232 233class unbreakable_space_node : public word_space_node { 234 unbreakable_space_node(hunits, int, color *, statem *, int, node * = 0); 235public: 236 unbreakable_space_node(hunits, color *, node * = 0); 237 node *copy(); 238 int reread(int *); 239 void tprint(troff_output_file *); 240 int same(node *); 241 void asciify(macro *); 242 const char *type(); 243 int force_tprint(); 244 int is_tag(); 245 breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); 246 int nbreaks(); 247 void split(int, node **, node **); 248 int merge_space(hunits, hunits, hunits); 249 node *add_self(node *, hyphen_list **); 250 hyphen_list *get_hyphen_list(hyphen_list *, int *); 251 hyphenation_type get_hyphenation_type(); 252}; 253 254class diverted_space_node : public node { 255public: 256 vunits n; 257 diverted_space_node(vunits, node * = 0); 258 diverted_space_node(vunits, statem *, int, node * = 0); 259 node *copy(); 260 int reread(int *); 261 int same(node *); 262 const char *type(); 263 int force_tprint(); 264 int is_tag(); 265}; 266 267class diverted_copy_file_node : public node { 268 symbol filename; 269public: 270 vunits n; 271 diverted_copy_file_node(symbol, node * = 0); 272 diverted_copy_file_node(symbol, statem *, int, node * = 0); 273 node *copy(); 274 int reread(int *); 275 int same(node *); 276 const char *type(); 277 int force_tprint(); 278 int is_tag(); 279}; 280 281class extra_size_node : public node { 282 vunits n; 283public: 284 extra_size_node(vunits); 285 extra_size_node(vunits, statem *, int); 286 void set_vertical_size(vertical_size *); 287 node *copy(); 288 int same(node *); 289 const char *type(); 290 int force_tprint(); 291 int is_tag(); 292}; 293 294class vertical_size_node : public node { 295 vunits n; 296public: 297 vertical_size_node(vunits, statem *, int); 298 vertical_size_node(vunits); 299 void set_vertical_size(vertical_size *); 300 void asciify(macro *); 301 node *copy(); 302 int set_unformat_flag(); 303 int same(node *); 304 const char *type(); 305 int force_tprint(); 306 int is_tag(); 307}; 308 309class hmotion_node : public node { 310protected: 311 hunits n; 312 unsigned char was_tab; 313 unsigned char unformat; 314 color *col; /* for grotty */ 315public: 316 hmotion_node(hunits i, color *c, node *nxt = 0) 317 : node(nxt), n(i), was_tab(0), unformat(0), col(c) {} 318 hmotion_node(hunits i, color *c, statem *s, int divlevel, node *nxt = 0) 319 : node(nxt, s, divlevel), n(i), was_tab(0), unformat(0), col(c) {} 320 hmotion_node(hunits i, int flag1, int flag2, color *c, statem *s, 321 int divlevel, node *nxt = 0) 322 : node(nxt, s, divlevel), n(i), was_tab(flag1), unformat(flag2), 323 col(c) {} 324 hmotion_node(hunits i, int flag1, int flag2, color *c, node *nxt = 0) 325 : node(nxt), n(i), was_tab(flag1), unformat(flag2), col(c) {} 326 node *copy(); 327 int reread(int *); 328 int set_unformat_flag(); 329 void asciify(macro *); 330 void tprint(troff_output_file *); 331 hunits width(); 332 void ascii_print(ascii_output_file *); 333 int same(node *); 334 const char *type(); 335 int force_tprint(); 336 int is_tag(); 337 node *add_self(node *, hyphen_list **); 338 hyphen_list *get_hyphen_list(hyphen_list *, int *); 339 hyphenation_type get_hyphenation_type(); 340}; 341 342class space_char_hmotion_node : public hmotion_node { 343public: 344 space_char_hmotion_node(hunits, color *, node * = 0); 345 space_char_hmotion_node(hunits, color *, statem *, int, node * = 0); 346 node *copy(); 347 void ascii_print(ascii_output_file *); 348 void asciify(macro *); 349 void tprint(troff_output_file *); 350 int same(node *); 351 const char *type(); 352 int force_tprint(); 353 int is_tag(); 354 node *add_self(node *, hyphen_list **); 355 hyphen_list *get_hyphen_list(hyphen_list *, int *); 356 hyphenation_type get_hyphenation_type(); 357}; 358 359class vmotion_node : public node { 360 vunits n; 361 color *col; /* for grotty */ 362public: 363 vmotion_node(vunits, color *); 364 vmotion_node(vunits, color *, statem *, int); 365 void tprint(troff_output_file *); 366 node *copy(); 367 vunits vertical_width(); 368 int same(node *); 369 const char *type(); 370 int force_tprint(); 371 int is_tag(); 372}; 373 374class hline_node : public node { 375 hunits x; 376 node *n; 377public: 378 hline_node(hunits, node *, node * = 0); 379 hline_node(hunits, node *, statem *, int, node * = 0); 380 ~hline_node(); 381 node *copy(); 382 hunits width(); 383 void tprint(troff_output_file *); 384 int same(node *); 385 const char *type(); 386 int force_tprint(); 387 int is_tag(); 388}; 389 390class vline_node : public node { 391 vunits x; 392 node *n; 393public: 394 vline_node(vunits, node *, node * = 0); 395 vline_node(vunits, node *, statem *, int, node * = 0); 396 ~vline_node(); 397 node *copy(); 398 void tprint(troff_output_file *); 399 hunits width(); 400 vunits vertical_width(); 401 void vertical_extent(vunits *, vunits *); 402 int same(node *); 403 const char *type(); 404 int force_tprint(); 405 int is_tag(); 406}; 407 408class dummy_node : public node { 409public: 410 dummy_node(node *nd = 0) : node(nd) {} 411 node *copy(); 412 int same(node *); 413 const char *type(); 414 int force_tprint(); 415 int is_tag(); 416 hyphenation_type get_hyphenation_type(); 417}; 418 419class transparent_dummy_node : public node { 420public: 421 transparent_dummy_node(node *nd = 0) : node(nd) {} 422 node *copy(); 423 int same(node *); 424 const char *type(); 425 int force_tprint(); 426 int is_tag(); 427 int ends_sentence(); 428 hyphenation_type get_hyphenation_type(); 429}; 430 431class zero_width_node : public node { 432 node *n; 433public: 434 zero_width_node(node *); 435 zero_width_node(node *, statem *, int); 436 ~zero_width_node(); 437 node *copy(); 438 void tprint(troff_output_file *); 439 int same(node *); 440 const char *type(); 441 int force_tprint(); 442 int is_tag(); 443 void append(node *); 444 int character_type(); 445 void vertical_extent(vunits *, vunits *); 446}; 447 448class left_italic_corrected_node : public node { 449 node *n; 450 hunits x; 451public: 452 left_italic_corrected_node(node * = 0); 453 left_italic_corrected_node(statem *, int, node * = 0); 454 ~left_italic_corrected_node(); 455 void tprint(troff_output_file *); 456 void ascii_print(ascii_output_file *); 457 void asciify(macro *); 458 node *copy(); 459 int same(node *); 460 const char *type(); 461 int force_tprint(); 462 int is_tag(); 463 hunits width(); 464 node *last_char_node(); 465 void vertical_extent(vunits *, vunits *); 466 int ends_sentence(); 467 int overlaps_horizontally(); 468 int overlaps_vertically(); 469 hyphenation_type get_hyphenation_type(); 470 tfont *get_tfont(); 471 int character_type(); 472 hunits skew(); 473 hunits italic_correction(); 474 hunits subscript_correction(); 475 hyphen_list *get_hyphen_list(hyphen_list *, int *); 476 node *add_self(node *, hyphen_list **); 477 node *merge_glyph_node(glyph_node *); 478}; 479 480class overstrike_node : public node { 481 node *list; 482 hunits max_width; 483public: 484 overstrike_node(); 485 overstrike_node(statem *, int); 486 ~overstrike_node(); 487 node *copy(); 488 void tprint(troff_output_file *); 489 void overstrike(node *); // add another node to be overstruck 490 hunits width(); 491 int same(node *); 492 const char *type(); 493 int force_tprint(); 494 int is_tag(); 495 node *add_self(node *, hyphen_list **); 496 hyphen_list *get_hyphen_list(hyphen_list *, int *); 497 hyphenation_type get_hyphenation_type(); 498}; 499 500class bracket_node : public node { 501 node *list; 502 hunits max_width; 503public: 504 bracket_node(); 505 bracket_node(statem *, int); 506 ~bracket_node(); 507 node *copy(); 508 void tprint(troff_output_file *); 509 void bracket(node *); // add another node to be overstruck 510 hunits width(); 511 int same(node *); 512 const char *type(); 513 int force_tprint(); 514 int is_tag(); 515}; 516 517class special_node : public node { 518 macro mac; 519 tfont *tf; 520 color *gcol; 521 color *fcol; 522 int no_init_string; 523 void tprint_start(troff_output_file *); 524 void tprint_char(troff_output_file *, unsigned char); 525 void tprint_end(troff_output_file *); 526public: 527 special_node(const macro &, int = 0); 528 special_node(const macro &, tfont *, color *, color *, statem *, int, 529 int = 0); 530 node *copy(); 531 void tprint(troff_output_file *); 532 int same(node *); 533 const char *type(); 534 int force_tprint(); 535 int is_tag(); 536 int ends_sentence(); 537 tfont *get_tfont(); 538}; 539 540class suppress_node : public node { 541 int is_on; 542 int emit_limits; // must we issue the extent of the area written out? 543 symbol filename; 544 char position; 545 int image_id; 546public: 547 suppress_node(int, int); 548 suppress_node(symbol, char, int); 549 suppress_node(int, int, symbol, char, int, statem *, int); 550 suppress_node(int, int, symbol, char, int); 551 node *copy(); 552 void tprint(troff_output_file *); 553 hunits width(); 554 int same(node *); 555 const char *type(); 556 int force_tprint(); 557 int is_tag(); 558private: 559 void put(troff_output_file *, const char *); 560}; 561 562class tag_node : public node { 563public: 564 string tag_string; 565 int delayed; 566 tag_node(); 567 tag_node(string, int); 568 tag_node(string, statem *, int, int); 569 node *copy(); 570 void tprint(troff_output_file *); 571 int same(node *); 572 const char *type(); 573 int force_tprint(); 574 int is_tag(); 575 int ends_sentence(); 576}; 577 578struct hvpair { 579 hunits h; 580 vunits v; 581 hvpair(); 582}; 583 584class draw_node : public node { 585 int npoints; 586 font_size sz; 587 color *gcol; 588 color *fcol; 589 char code; 590 hvpair *point; 591public: 592 draw_node(char, hvpair *, int, font_size, color *, color *); 593 draw_node(char, hvpair *, int, font_size, color *, color *, statem *, int); 594 ~draw_node(); 595 hunits width(); 596 vunits vertical_width(); 597 node *copy(); 598 void tprint(troff_output_file *); 599 int same(node *); 600 const char *type(); 601 int force_tprint(); 602 int is_tag(); 603}; 604 605class charinfo; 606node *make_node(charinfo *, environment *); 607int character_exists(charinfo *, environment *); 608 609int same_node_list(node *, node *); 610node *reverse_node_list(node *); 611void delete_node_list(node *); 612node *copy_node_list(node *); 613 614int get_bold_fontno(int); 615 616inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p) 617: hyphen(0), breakable(0), hyphenation_code(code), next(p) 618{ 619} 620 621extern void read_desc(); 622extern int mount_font(int, symbol, symbol = NULL_SYMBOL); 623extern int check_font(symbol, symbol); 624extern int check_style(symbol); 625extern void mount_style(int, symbol); 626extern int is_good_fontno(int); 627extern int symbol_fontno(symbol); 628extern int next_available_font_position(); 629extern void init_size_table(int *); 630extern int get_underline_fontno(); 631 632class output_file { 633 char make_g_plus_plus_shut_up; 634public: 635 output_file(); 636 virtual ~output_file(); 637 virtual void trailer(vunits); 638 virtual void flush() = 0; 639 virtual void transparent_char(unsigned char) = 0; 640 virtual void print_line(hunits x, vunits y, node *n, 641 vunits before, vunits after, hunits width) = 0; 642 virtual void begin_page(int pageno, vunits page_length) = 0; 643 virtual void copy_file(hunits x, vunits y, const char *filename) = 0; 644 virtual int is_printing() = 0; 645 virtual void put_filename(const char *); 646 virtual void on(); 647 virtual void off(); 648#ifdef COLUMN 649 virtual void vjustify(vunits, symbol); 650#endif /* COLUMN */ 651 mtsm state; 652}; 653 654#ifndef POPEN_MISSING 655extern char *pipe_command; 656#endif 657 658extern output_file *the_output; 659extern void init_output(); 660int in_output_page_list(int); 661 662class font_family { 663 int *map; 664 int map_size; 665public: 666 const symbol nm; 667 font_family(symbol); 668 ~font_family(); 669 int make_definite(int); 670 static void invalidate_fontno(int); 671}; 672 673font_family *lookup_family(symbol); 674symbol get_font_name(int, environment *); 675symbol get_style_name(int); 676extern search_path include_search_path; 677