diff options
Diffstat (limited to 'src/roff/troff/node.cc')
-rw-r--r-- | src/roff/troff/node.cc | 434 |
1 files changed, 413 insertions, 21 deletions
diff --git a/src/roff/troff/node.cc b/src/roff/troff/node.cc index 44ccda7bb..3770aab9f 100644 --- a/src/roff/troff/node.cc +++ b/src/roff/troff/node.cc @@ -55,6 +55,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #endif /* not _POSIX_VERSION */ +/* + * how many boundaries of images have been written? Useful for + * debugging grohtml + */ + +static int image_no=0; +static int suppress_start_page=0; + #define STORE_WIDTH 1 symbol HYPHEN_SYMBOL("hy"); @@ -322,7 +330,7 @@ void font_info::set_conditional_bold(int fontno, hunits offset) } conditional_bold::conditional_bold(int f, hunits h, conditional_bold *x) - : next(x), fontno(f), offset(h) +: next(x), fontno(f), offset(h) { } @@ -405,9 +413,9 @@ hunits font_info::get_half_narrow_space_width(font_size fs) tfont_spec::tfont_spec(symbol nm, int n, font *f, font_size s, int h, int sl) - : name(nm), input_position(n), fm(f), size(s), - is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1), - height(h), slant(sl) +: name(nm), input_position(n), fm(f), size(s), + is_bold(0), is_constant_spaced(0), ligature_mode(1), kern_mode(1), + height(h), slant(sl) { if (height == size.to_scaled_points()) height = 0; @@ -671,6 +679,7 @@ public: void put_filename(const char *filename); void on(); void off(); + int is_on(); int is_printing(); void copy_file(hunits x, vunits y, const char *filename); }; @@ -742,6 +751,7 @@ public: void right(hunits); void down(vunits); void moveto(hunits, vunits); + void start_special(tfont *tf); void start_special(); void special_char(unsigned char c); void end_special(); @@ -785,6 +795,22 @@ inline void troff_output_file::put(int i) put_string(i_to_a(i), fp); } +void troff_output_file::start_special(tfont *tf) +{ + flush_tbuf(); + + /* + * although this is extremely unlikely to have an effect on other devices + * this way is safer. Currently this is only needed for html. + */ + if (is_html && tf) { + if (tf != current_tfont) + set_font(tf); + } + do_motion(); + put("x X "); +} + void troff_output_file::start_special() { flush_tbuf(); @@ -815,7 +841,8 @@ void troff_output_file::really_print_line(hunits x, vunits y, node *n, { moveto(x, y); while (n != 0) { - n->tprint(this); + if (is_on() || (n->force_tprint())) + n->tprint(this); n = n->next; } flush_tbuf(); @@ -1367,7 +1394,7 @@ void real_output_file::transparent_char(unsigned char c) void real_output_file::print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width) { - if (printing && output_on) + if (printing) really_print_line(x, y, n, before, after, width); delete_node_list(n); } @@ -1392,10 +1419,6 @@ void real_output_file::on() if (output_on == 0) { output_on = 1; } - /* - * lastly we reset the output registers - */ - reset_output_registers(); } void real_output_file::off() @@ -1404,6 +1427,11 @@ void real_output_file::off() output_on = 0; } +int real_output_file::is_on() +{ + return( output_on ); +} + void real_output_file::really_on() { } @@ -1527,6 +1555,7 @@ public: int character_type(); int same(node *); const char *type(); + int force_tprint(); }; glyph_node *glyph_node::free_list = 0; @@ -1549,6 +1578,7 @@ public: void asciify(macro *); int same(node *); const char *type(); + int force_tprint(); }; class kern_pair_node : public node { @@ -1574,6 +1604,7 @@ public: void asciify(macro *); int same(node *); const char *type(); + int force_tprint(); void vertical_extent(vunits *, vunits *); }; @@ -1602,6 +1633,7 @@ public: void asciify(macro *); int same(node *); const char *type(); + int force_tprint(); }; void *glyph_node::operator new(size_t n) @@ -1793,14 +1825,14 @@ void glyph_node::ascii_print(ascii_output_file *ascii) ligature_node::ligature_node(charinfo *c, tfont *t, node *gn1, node *gn2, node *x) - : glyph_node(c, t, x), n1(gn1), n2(gn2) +: glyph_node(c, t, x), n1(gn1), n2(gn2) { } #ifdef STORE_WIDTH ligature_node::ligature_node(charinfo *c, tfont *t, hunits w, node *gn1, node *gn2, node *x) - : glyph_node(c, t, w, x), n1(gn1), n2(gn2) +: glyph_node(c, t, w, x), n1(gn1), n2(gn2) { } #endif @@ -1841,12 +1873,12 @@ node *ligature_node::add_self(node *n, hyphen_list **p) } kern_pair_node::kern_pair_node(hunits n, node *first, node *second, node *x) - : node(x), amount(n), n1(first), n2(second) +: node(x), amount(n), n1(first), n2(second) { } dbreak_node::dbreak_node(node *n, node *p, node *x) - : node(x), none(n), pre(p), post(0) +: node(x), none(n), pre(p), post(0) { } @@ -2005,6 +2037,7 @@ public: node *copy(); int same(node *); const char *type(); + int force_tprint(); hyphenation_type get_hyphenation_type(); }; @@ -2027,6 +2060,11 @@ const char *hyphen_inhibitor_node::type() return "hyphen_inhibitor_node"; } +int hyphen_inhibitor_node::force_tprint() +{ + return 0; +} + hyphenation_type hyphen_inhibitor_node::get_hyphenation_type() { return HYPHEN_INHIBIT; @@ -2096,6 +2134,11 @@ node *node::last_char_node() return 0; } +int node::force_tprint() +{ + return 0; +} + hunits hmotion_node::width() { return n; @@ -2172,6 +2215,7 @@ public: hunits skew(); node *add_self(node *, hyphen_list **); const char *type(); + int force_tprint(); }; node *node::add_italic_correction(hunits *width) @@ -2309,6 +2353,7 @@ public: tfont *get_tfont(); int same(node *); const char *type(); + int force_tprint(); }; break_char_node::break_char_node(node *n, int c, node *x) @@ -2657,6 +2702,11 @@ node *space_node::copy() return new space_node(n, set); } +int space_node::force_tprint() +{ + return 0; +} + int space_node::nspaces() { return set ? 0 : 1; @@ -3216,11 +3266,25 @@ int node::interpret(macro *) special_node::special_node(const macro &m) : mac(m) { + font_size fs = curenv->get_font_size(); + int char_height = curenv->get_char_height(); + int char_slant = curenv->get_char_slant(); + int fontno = curenv->get_font(); + tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, + fontno); + if (curenv->is_composite()) + tf = tf->get_plain(); +} + +special_node::special_node(const macro &m, tfont *t) +: mac(m), tf(t) +{ } int special_node::same(node *n) { - return mac == ((special_node *)n)->mac; + return ((mac == ((special_node *)n)->mac) && + (tf == ((special_node *)n)->tf)); } const char *special_node::type() @@ -3228,14 +3292,19 @@ const char *special_node::type() return "special_node"; } +int special_node::force_tprint() +{ + return 0; +} + node *special_node::copy() { - return new special_node(mac); + return new special_node(mac, tf); } void special_node::tprint_start(troff_output_file *out) { - out->start_special(); + out->start_special(get_tfont()); } void special_node::tprint_char(troff_output_file *out, unsigned char c) @@ -3248,6 +3317,200 @@ void special_node::tprint_end(troff_output_file *out) out->end_special(); } +tfont *special_node::get_tfont() +{ + return tf; +} + +/* suppress_node */ + +suppress_node::suppress_node(int on_or_off, int issue_limits) +: is_on(on_or_off), emit_limits(issue_limits), filename(0), position(0) +{ +} + +suppress_node::suppress_node(symbol f, char p) +: is_on(2), emit_limits(0), filename(f), position(p) +{ +} + +suppress_node::suppress_node(int issue_limits, int on_or_off, symbol f, char p) +: is_on(on_or_off), emit_limits(issue_limits), filename(f), position(p) +{ +} + +int suppress_node::same(node *n) +{ + return ((is_on == ((suppress_node *)n)->is_on) + && (emit_limits == ((suppress_node *)n)->emit_limits) + && (filename == ((suppress_node *)n)->filename) + && (position == ((suppress_node *)n)->position)); +; +} + +const char *suppress_node::type() +{ + return "suppress_node"; +} + +node *suppress_node::copy() +{ + return new suppress_node(emit_limits, is_on, filename, position); +} + +int get_reg_int (const char *p) +{ + reg *r = (reg *)number_reg_dictionary.lookup(p); + units prev_value; + if (r && (r->get_value(&prev_value))) + return( (int)prev_value ); + else + warning(WARN_REG, "number register `%1' not defined", p); + return( 0 ); +} + +const char *get_reg_str (const char *p) +{ + reg *r = (reg *)number_reg_dictionary.lookup(p); + if (r) + return r->get_string(); + else + warning(WARN_REG, "register `%1' not defined", p); + return( 0 ); +} + +void suppress_node::put(troff_output_file *out, const char *s) +{ + int i=0; + + while (s[i] != (char)0) { + out->special_char(s[i]); + i++; + } +} + +/* + * We prefer to remember the last position, rather than have a .html-start + * followed by html-end-center, html-end-left as it is more natural to + * express an image by: + * + * .html-image-left + * + * .html-image-end + * + * similar to other troff commands, although this method is slightly more + * messy to implement. + */ + +static char last_position = 0; +static const char *last_image_filename = 0; + +inline int min(int a, int b) +{ + return a < b ? a : b; +} + +/* + * tprint - if (is_on == 2) + * remember current position (l, r, c, i) and filename + * else + * if (emit_limits) + * if (html) + * emit image tag + * else + * emit postscript bounds for image + * else + * if (suppress boolean differs from current state) + * alter state + * reset registers + * record current page + * set low water mark. + */ + +void suppress_node::tprint(troff_output_file *out) +{ + int current_page = get_reg_int("%"); + // firstly check to see whether this suppress node contains + // an image filename & position. + if (is_on == 2) { + // remember position and filename + last_position = position; + last_image_filename = filename.contents(); + } + else { + // now check whether the suppress node requires us to issue limits. + if (emit_limits) { + char name[8192]; + image_no++; + // remember that the filename will contain a %d in which the + // image_no is placed + sprintf(name, last_image_filename, image_no); + if (is_html) { + switch (last_position) { + case 'c': + out->start_special(); + put(out, "html-tag:.centered-image"); + break; + case 'r': + out->start_special(); + put(out, "html-tag:.right-image"); + break; + case 'l': + out->start_special(); + put(out, "html-tag:.left-image"); + break; + case 'i': + ; + default: + ; + } + out->end_special(); + out->start_special(); + put(out, "html-tag:.auto-image "); + put(out, name); + out->end_special(); + } + else { + // postscript (or other device) + if (current_page != suppress_start_page) + error("suppression limit registers span more than one page;\n" + "image description %1 will be wrong", image_no); + // remember that the filename will contain a %d in which the + // image_no is placed */ + fprintf(stderr, + "grohtml-info:page %d %d %d %d %d %d %s %d %d %s\n", + current_page, + get_reg_int("opminx"), get_reg_int("opminy"), + get_reg_int("opmaxx"), min(get_reg_int("opmaxy"), + out->get_vpos()), + // page offset + line length + get_reg_int(".o") + get_reg_int(".l"), + name, hresolution, vresolution, get_reg_str(".F")); + fflush(stderr); + } + } + else { + if (is_on) + out->on(); + else + out->off(); + // lastly we reset the output registers + reset_output_registers(out->get_vpos()); + suppress_start_page = current_page; + } + } +} + +int suppress_node::force_tprint() +{ + return is_on; +} + +hunits suppress_node::width() +{ + return H0; +} + /* composite_node */ class composite_node : public charinfo_node { @@ -3269,6 +3532,7 @@ public: tfont *get_tfont(); int same(node *); const char *type(); + int force_tprint(); void vertical_extent(vunits *, vunits *); vunits vertical_width(); }; @@ -3433,6 +3697,11 @@ node *unbreakable_space_node::copy() return new unbreakable_space_node(n, set, num_spaces); } +int unbreakable_space_node::force_tprint() +{ + return 0; +} + breakpoint *unbreakable_space_node::get_breakpoints(hunits, int, breakpoint *rest, int) { @@ -3459,7 +3728,7 @@ hvpair::hvpair() } draw_node::draw_node(char c, hvpair *p, int np, font_size s) - : npoints(np), sz(s), code(c) +: npoints(np), sz(s), code(c) { point = new hvpair[npoints]; for (int i = 0; i < npoints; i++) @@ -3482,6 +3751,11 @@ const char *draw_node::type() return "draw_node"; } +int draw_node::force_tprint() +{ + return 0; +} + draw_node::~draw_node() { if (point) @@ -4035,6 +4309,11 @@ const char *extra_size_node::type() return "extra_size_node"; } +int extra_size_node::force_tprint() +{ + return 0; +} + int vertical_size_node::same(node *nd) { return n == ((vertical_size_node *)nd)->n; @@ -4045,6 +4324,11 @@ const char *vertical_size_node::type() return "vertical_size_node"; } +int vertical_size_node::force_tprint() +{ + return 0; +} + int hmotion_node::same(node *nd) { return n == ((hmotion_node *)nd)->n; @@ -4055,6 +4339,11 @@ const char *hmotion_node::type() return "hmotion_node"; } +int hmotion_node::force_tprint() +{ + return 0; +} + int space_char_hmotion_node::same(node *nd) { return n == ((space_char_hmotion_node *)nd)->n; @@ -4065,6 +4354,11 @@ const char *space_char_hmotion_node::type() return "space_char_hmotion_node"; } +int space_char_hmotion_node::force_tprint() +{ + return 0; +} + int vmotion_node::same(node *nd) { return n == ((vmotion_node *)nd)->n; @@ -4075,6 +4369,11 @@ const char *vmotion_node::type() return "vmotion_node"; } +int vmotion_node::force_tprint() +{ + return 0; +} + int hline_node::same(node *nd) { return x == ((hline_node *)nd)->x && same_node(n, ((hline_node *)nd)->n); @@ -4085,6 +4384,11 @@ const char *hline_node::type() return "hline_node"; } +int hline_node::force_tprint() +{ + return 0; +} + int vline_node::same(node *nd) { return x == ((vline_node *)nd)->x && same_node(n, ((vline_node *)nd)->n); @@ -4095,6 +4399,11 @@ const char *vline_node::type() return "vline_node"; } +int vline_node::force_tprint() +{ + return 0; +} + int dummy_node::same(node * /*nd*/) { return 1; @@ -4105,6 +4414,11 @@ const char *dummy_node::type() return "dummy_node"; } +int dummy_node::force_tprint() +{ + return 0; +} + int transparent_dummy_node::same(node * /*nd*/) { return 1; @@ -4115,6 +4429,11 @@ const char *transparent_dummy_node::type() return "transparent_dummy_node"; } +int transparent_dummy_node::force_tprint() +{ + return 0; +} + int transparent_dummy_node::ends_sentence() { return 2; @@ -4130,6 +4449,11 @@ const char *zero_width_node::type() return "zero_width_node"; } +int zero_width_node::force_tprint() +{ + return 0; +} + int italic_corrected_node::same(node *nd) { return (x == ((italic_corrected_node *)nd)->x @@ -4141,6 +4465,10 @@ const char *italic_corrected_node::type() return "italic_corrected_node"; } +int italic_corrected_node::force_tprint() +{ + return 0; +} left_italic_corrected_node::left_italic_corrected_node(node *x) : node(x), n(0) @@ -4196,6 +4524,11 @@ const char *left_italic_corrected_node::type() return "left_italic_corrected_node"; } +int left_italic_corrected_node::force_tprint() +{ + return 0; +} + int left_italic_corrected_node::same(node *nd) { return (x == ((left_italic_corrected_node *)nd)->x @@ -4300,6 +4633,11 @@ const char *overstrike_node::type() return "overstrike_node"; } +int overstrike_node::force_tprint() +{ + return 0; +} + int bracket_node::same(node *nd) { return same_node_list(list, ((bracket_node *)nd)->list); @@ -4310,6 +4648,11 @@ const char *bracket_node::type() return "bracket_node"; } +int bracket_node::force_tprint() +{ + return 0; +} + int composite_node::same(node *nd) { return ci == ((composite_node *)nd)->ci @@ -4321,6 +4664,11 @@ const char *composite_node::type() return "composite_node"; } +int composite_node::force_tprint() +{ + return 0; +} + int glyph_node::same(node *nd) { return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf; @@ -4331,6 +4679,11 @@ const char *glyph_node::type() return "glyph_node"; } +int glyph_node::force_tprint() +{ + return 0; +} + int ligature_node::same(node *nd) { return (same_node(n1, ((ligature_node *)nd)->n1) @@ -4343,6 +4696,11 @@ const char *ligature_node::type() return "ligature_node"; } +int ligature_node::force_tprint() +{ + return 0; +} + int kern_pair_node::same(node *nd) { return (amount == ((kern_pair_node *)nd)->amount @@ -4355,6 +4713,11 @@ const char *kern_pair_node::type() return "kern_pair_node"; } +int kern_pair_node::force_tprint() +{ + return 0; +} + int dbreak_node::same(node *nd) { return (same_node_list(none, ((dbreak_node *)nd)->none) @@ -4367,6 +4730,11 @@ const char *dbreak_node::type() return "dbreak_node"; } +int dbreak_node::force_tprint() +{ + return 0; +} + int break_char_node::same(node *nd) { return (break_code == ((break_char_node *)nd)->break_code @@ -4378,6 +4746,11 @@ const char *break_char_node::type() return "break_char_node"; } +int break_char_node::force_tprint() +{ + return 0; +} + int line_start_node::same(node * /*nd*/) { return 1; @@ -4388,6 +4761,11 @@ const char *line_start_node::type() return "line_start_node"; } +int line_start_node::force_tprint() +{ + return 0; +} + int space_node::same(node *nd) { return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set; @@ -4409,6 +4787,11 @@ const char *word_space_node::type() return "word_space_node"; } +int word_space_node::force_tprint() +{ + return 0; +} + int unbreakable_space_node::same(node *nd) { return (n == ((unbreakable_space_node *)nd)->n @@ -4430,6 +4813,11 @@ const char *diverted_space_node::type() return "diverted_space_node"; } +int diverted_space_node::force_tprint() +{ + return 0; +} + int diverted_copy_file_node::same(node *nd) { return filename == ((diverted_copy_file_node *)nd)->filename; @@ -4440,6 +4828,11 @@ const char *diverted_copy_file_node::type() return "diverted_copy_file_node"; } +int diverted_copy_file_node::force_tprint() +{ + return 0; +} + // Grow the font_table so that its size is > n. static void grow_font_table(int n) @@ -4872,9 +5265,8 @@ track_kerning_function::track_kerning_function() : non_zero(0) track_kerning_function::track_kerning_function(int min_s, hunits min_a, int max_s, hunits max_a) - : non_zero(1), - min_size(min_s), min_amount(min_a), - max_size(max_s), max_amount(max_a) +: non_zero(1), min_size(min_s), min_amount(min_a), max_size(max_s), + max_amount(max_a) { } |