// -*- C++ -*- /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. groff is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. groff is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with groff; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ struct hyphen_list { unsigned char hyphen; unsigned char breakable; unsigned char hyphenation_code; hyphen_list *next; hyphen_list(unsigned char code, hyphen_list *p = 0); }; void hyphenate(hyphen_list *, unsigned); enum hyphenation_type { HYPHEN_MIDDLE, HYPHEN_BOUNDARY, HYPHEN_INHIBIT }; class ascii_output_file; struct breakpoint; struct vertical_size; class charinfo; class macro; class troff_output_file; class tfont; class environment; class glyph_node; class diverted_space_node; class token_node; struct node { node *next; node *last; statem *state; statem *push_state; int div_nest_level; int is_special; node(); node(node *); node(node *, statem *, int); node *add_char(charinfo *, environment *, hunits *, int *, node ** = 0); virtual ~node(); virtual node *copy() = 0; virtual int set_unformat_flag(); virtual int force_tprint() = 0; virtual int is_tag() = 0; virtual hunits width(); virtual hunits subscript_correction(); virtual hunits italic_correction(); virtual hunits left_italic_correction(); virtual hunits skew(); virtual int nspaces(); virtual int merge_space(hunits, hunits, hunits); virtual vunits vertical_width(); virtual node *last_char_node(); virtual void vertical_extent(vunits *, vunits *); virtual int character_type(); virtual void set_vertical_size(vertical_size *); virtual int ends_sentence(); virtual node *merge_self(node *); virtual node *add_discretionary_hyphen(); virtual node *add_self(node *, hyphen_list **); virtual hyphen_list *get_hyphen_list(hyphen_list *, int *); virtual void ascii_print(ascii_output_file *); virtual void asciify(macro *); virtual int discardable(); virtual void spread_space(int *, hunits *); virtual void freeze_space(); virtual void is_escape_colon(); virtual breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); virtual int nbreaks(); virtual void split(int, node **, node **); virtual hyphenation_type get_hyphenation_type(); virtual int reread(int *); virtual token_node *get_token_node(); virtual int overlaps_vertically(); virtual int overlaps_horizontally(); virtual units size(); virtual int interpret(macro *); virtual node *merge_glyph_node(glyph_node *); virtual tfont *get_tfont(); virtual color *get_glyph_color(); virtual color *get_fill_color(); virtual void tprint(troff_output_file *); virtual void zero_width_tprint(troff_output_file *); node *add_italic_correction(hunits *); virtual int same(node *) = 0; virtual const char *type() = 0; virtual void debug_node(); virtual void debug_node_list(); }; inline node::node() : next(0), last(0), state(0), push_state(0), div_nest_level(0), is_special(0) { } inline node::node(node *n) : next(n), last(0), state(0), push_state(0), div_nest_level(0), is_special(0) { } inline node::node(node *n, statem *s, int divlevel) : next(n), last(0), push_state(0), div_nest_level(divlevel), is_special(0) { if (s) state = new statem(s); else state = 0; } inline node::~node() { } // 0 means it doesn't, 1 means it does, 2 means it's transparent int node_list_ends_sentence(node *); struct breakpoint { breakpoint *next; hunits width; int nspaces; node *nd; int index; char hyphenated; }; class line_start_node : public node { public: line_start_node() {} node *copy() { return new line_start_node; } int same(node *); int force_tprint(); int is_tag(); const char *type(); void asciify(macro *); }; class space_node : public node { private: #if 0 enum { BLOCK = 1024 }; static space_node *free_list; void operator delete(void *); #endif protected: hunits n; char set; char was_escape_colon; color *col; /* for grotty */ space_node(hunits, int, int, color *, statem *, int, node * = 0); public: space_node(hunits, color *, statem *, int, node * = 0); space_node(hunits, color *, node * = 0); #if 0 ~space_node(); void *operator new(size_t); #endif node *copy(); int nspaces(); hunits width(); int discardable(); int merge_space(hunits, hunits, hunits); void freeze_space(); void is_escape_colon(); void spread_space(int *, hunits *); void tprint(troff_output_file *); breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); int nbreaks(); void split(int, node **, node **); void ascii_print(ascii_output_file *); int same(node *); void asciify(macro *); const char *type(); int force_tprint(); int is_tag(); hyphenation_type get_hyphenation_type(); }; struct width_list { hunits width; hunits sentence_width; width_list *next; width_list(hunits, hunits); width_list(width_list *); }; class word_space_node : public space_node { protected: width_list *orig_width; unsigned char unformat; word_space_node(hunits, int, color *, width_list *, int, statem *, int, node * = 0); public: word_space_node(hunits, color *, width_list *, node * = 0); ~word_space_node(); node *copy(); int reread(int *); int set_unformat_flag(); void tprint(troff_output_file *); int same(node *); void asciify(macro *); const char *type(); int merge_space(hunits, hunits, hunits); int force_tprint(); int is_tag(); }; class unbreakable_space_node : public word_space_node { unbreakable_space_node(hunits, int, color *, statem *, int, node * = 0); public: unbreakable_space_node(hunits, color *, node * = 0); node *copy(); int reread(int *); void tprint(troff_output_file *); int same(node *); void asciify(macro *); const char *type(); int force_tprint(); int is_tag(); breakpoint *get_breakpoints(hunits, int, breakpoint * = 0, int = 0); int nbreaks(); void split(int, node **, node **); int merge_space(hunits, hunits, hunits); node *add_self(node *, hyphen_list **); hyphen_list *get_hyphen_list(hyphen_list *, int *); hyphenation_type get_hyphenation_type(); }; class diverted_space_node : public node { public: vunits n; diverted_space_node(vunits, node * = 0); diverted_space_node(vunits, statem *, int, node * = 0); node *copy(); int reread(int *); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class diverted_copy_file_node : public node { symbol filename; public: vunits n; diverted_copy_file_node(symbol, node * = 0); diverted_copy_file_node(symbol, statem *, int, node * = 0); node *copy(); int reread(int *); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class extra_size_node : public node { vunits n; public: extra_size_node(vunits); extra_size_node(vunits, statem *, int); void set_vertical_size(vertical_size *); node *copy(); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class vertical_size_node : public node { vunits n; public: vertical_size_node(vunits, statem *, int); vertical_size_node(vunits); void set_vertical_size(vertical_size *); void asciify(macro *); node *copy(); int set_unformat_flag(); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class hmotion_node : public node { protected: hunits n; unsigned char was_tab; unsigned char unformat; color *col; /* for grotty */ public: hmotion_node(hunits i, color *c, node *nxt = 0) : node(nxt), n(i), was_tab(0), unformat(0), col(c) {} hmotion_node(hunits i, color *c, statem *s, int divlevel, node *nxt = 0) : node(nxt, s, divlevel), n(i), was_tab(0), unformat(0), col(c) {} hmotion_node(hunits i, int flag1, int flag2, color *c, statem *s, int divlevel, node *nxt = 0) : node(nxt, s, divlevel), n(i), was_tab(flag1), unformat(flag2), col(c) {} hmotion_node(hunits i, int flag1, int flag2, color *c, node *nxt = 0) : node(nxt), n(i), was_tab(flag1), unformat(flag2), col(c) {} node *copy(); int reread(int *); int set_unformat_flag(); void asciify(macro *); void tprint(troff_output_file *); hunits width(); void ascii_print(ascii_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); node *add_self(node *, hyphen_list **); hyphen_list *get_hyphen_list(hyphen_list *, int *); hyphenation_type get_hyphenation_type(); }; class space_char_hmotion_node : public hmotion_node { public: space_char_hmotion_node(hunits, color *, node * = 0); space_char_hmotion_node(hunits, color *, statem *, int, node * = 0); node *copy(); void ascii_print(ascii_output_file *); void asciify(macro *); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); node *add_self(node *, hyphen_list **); hyphen_list *get_hyphen_list(hyphen_list *, int *); hyphenation_type get_hyphenation_type(); }; class vmotion_node : public node { vunits n; color *col; /* for grotty */ public: vmotion_node(vunits, color *); vmotion_node(vunits, color *, statem *, int); void tprint(troff_output_file *); node *copy(); vunits vertical_width(); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class hline_node : public node { hunits x; node *n; public: hline_node(hunits, node *, node * = 0); hline_node(hunits, node *, statem *, int, node * = 0); ~hline_node(); node *copy(); hunits width(); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class vline_node : public node { vunits x; node *n; public: vline_node(vunits, node *, node * = 0); vline_node(vunits, node *, statem *, int, node * = 0); ~vline_node(); node *copy(); void tprint(troff_output_file *); hunits width(); vunits vertical_width(); void vertical_extent(vunits *, vunits *); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class dummy_node : public node { public: dummy_node(node *nd = 0) : node(nd) {} node *copy(); int same(node *); const char *type(); int force_tprint(); int is_tag(); hyphenation_type get_hyphenation_type(); }; class transparent_dummy_node : public node { public: transparent_dummy_node(node *nd = 0) : node(nd) {} node *copy(); int same(node *); const char *type(); int force_tprint(); int is_tag(); int ends_sentence(); hyphenation_type get_hyphenation_type(); }; class zero_width_node : public node { node *n; public: zero_width_node(node *); zero_width_node(node *, statem *, int); ~zero_width_node(); node *copy(); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); void append(node *); int character_type(); void vertical_extent(vunits *, vunits *); }; class left_italic_corrected_node : public node { node *n; hunits x; public: left_italic_corrected_node(node * = 0); left_italic_corrected_node(statem *, int, node * = 0); ~left_italic_corrected_node(); void tprint(troff_output_file *); void ascii_print(ascii_output_file *); void asciify(macro *); node *copy(); int same(node *); const char *type(); int force_tprint(); int is_tag(); hunits width(); node *last_char_node(); void vertical_extent(vunits *, vunits *); int ends_sentence(); int overlaps_horizontally(); int overlaps_vertically(); hyphenation_type get_hyphenation_type(); tfont *get_tfont(); int character_type(); hunits skew(); hunits italic_correction(); hunits subscript_correction(); hyphen_list *get_hyphen_list(hyphen_list *, int *); node *add_self(node *, hyphen_list **); node *merge_glyph_node(glyph_node *); }; class overstrike_node : public node { node *list; hunits max_width; public: overstrike_node(); overstrike_node(statem *, int); ~overstrike_node(); node *copy(); void tprint(troff_output_file *); void overstrike(node *); // add another node to be overstruck hunits width(); int same(node *); const char *type(); int force_tprint(); int is_tag(); node *add_self(node *, hyphen_list **); hyphen_list *get_hyphen_list(hyphen_list *, int *); hyphenation_type get_hyphenation_type(); }; class bracket_node : public node { node *list; hunits max_width; public: bracket_node(); bracket_node(statem *, int); ~bracket_node(); node *copy(); void tprint(troff_output_file *); void bracket(node *); // add another node to be overstruck hunits width(); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class special_node : public node { macro mac; tfont *tf; color *gcol; color *fcol; int no_init_string; void tprint_start(troff_output_file *); void tprint_char(troff_output_file *, unsigned char); void tprint_end(troff_output_file *); public: special_node(const macro &, int = 0); special_node(const macro &, tfont *, color *, color *, statem *, int, int = 0); node *copy(); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); int ends_sentence(); tfont *get_tfont(); }; class suppress_node : public node { int is_on; int emit_limits; // must we issue the extent of the area written out? symbol filename; char position; int image_id; public: suppress_node(int, int); suppress_node(symbol, char, int); suppress_node(int, int, symbol, char, int, statem *, int); suppress_node(int, int, symbol, char, int); node *copy(); void tprint(troff_output_file *); hunits width(); int same(node *); const char *type(); int force_tprint(); int is_tag(); private: void put(troff_output_file *, const char *); }; class tag_node : public node { public: string tag_string; int delayed; tag_node(); tag_node(string, int); tag_node(string, statem *, int, int); node *copy(); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); int ends_sentence(); }; struct hvpair { hunits h; vunits v; hvpair(); }; class draw_node : public node { int npoints; font_size sz; color *gcol; color *fcol; char code; hvpair *point; public: draw_node(char, hvpair *, int, font_size, color *, color *); draw_node(char, hvpair *, int, font_size, color *, color *, statem *, int); ~draw_node(); hunits width(); vunits vertical_width(); node *copy(); void tprint(troff_output_file *); int same(node *); const char *type(); int force_tprint(); int is_tag(); }; class charinfo; node *make_node(charinfo *, environment *); int character_exists(charinfo *, environment *); int same_node_list(node *, node *); node *reverse_node_list(node *); void delete_node_list(node *); node *copy_node_list(node *); int get_bold_fontno(int); inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p) : hyphen(0), breakable(0), hyphenation_code(code), next(p) { } extern void read_desc(); extern int mount_font(int, symbol, symbol = NULL_SYMBOL); extern int check_font(symbol, symbol); extern int check_style(symbol); extern void mount_style(int, symbol); extern int is_good_fontno(int); extern int symbol_fontno(symbol); extern int next_available_font_position(); extern void init_size_table(int *); extern int get_underline_fontno(); class output_file { char make_g_plus_plus_shut_up; public: output_file(); virtual ~output_file(); virtual void trailer(vunits); virtual void flush() = 0; virtual void transparent_char(unsigned char) = 0; virtual void print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width) = 0; virtual void begin_page(int pageno, vunits page_length) = 0; virtual void copy_file(hunits x, vunits y, const char *filename) = 0; virtual int is_printing() = 0; virtual void put_filename(const char *); virtual void on(); virtual void off(); #ifdef COLUMN virtual void vjustify(vunits, symbol); #endif /* COLUMN */ mtsm state; }; #ifndef POPEN_MISSING extern char *pipe_command; #endif extern output_file *the_output; extern void init_output(); int in_output_page_list(int); class font_family { int *map; int map_size; public: const symbol nm; font_family(symbol); ~font_family(); int make_definite(int); static void invalidate_fontno(int); }; font_family *lookup_family(symbol); symbol get_font_name(int, environment *); symbol get_style_name(int); extern search_path include_search_path;