diff options
Diffstat (limited to 'contrib/groff/src/roff/troff/node.cc')
-rw-r--r-- | contrib/groff/src/roff/troff/node.cc | 650 |
1 files changed, 457 insertions, 193 deletions
diff --git a/contrib/groff/src/roff/troff/node.cc b/contrib/groff/src/roff/troff/node.cc index 2d2d799..650bf0e 100644 --- a/contrib/groff/src/roff/troff/node.cc +++ b/contrib/groff/src/roff/troff/node.cc @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -19,11 +19,12 @@ 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "troff.h" + #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#include "troff.h" #include "symbol.h" #include "dictionary.h" #include "hvunits.h" @@ -35,6 +36,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "font.h" #include "reg.h" #include "input.h" +#include "div.h" +#include "geometry.h" #include "nonposix.h" @@ -60,8 +63,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ * debugging grohtml */ -static int image_no=0; -static int suppress_start_page=0; +int image_no = 0; +static int suppress_start_page = 0; #define STORE_WIDTH 1 @@ -147,6 +150,7 @@ public: int get_bold(hunits *); int is_special(); int is_style(); + friend symbol get_font_name(int, environment *); }; class tfont_spec { @@ -234,6 +238,14 @@ inline int font_info::is_style() return fm == 0; } +tfont *make_tfont(tfont_spec &spec) +{ + for (tfont *p = tfont::tfont_list; p; p = p->next) + if (*p == spec) + return p; + return new tfont(spec); +} + // this is the current_font, fontno is where we found the character, // presumably a special font @@ -378,6 +390,15 @@ symbol font_info::get_name() return internal_name; } +symbol get_font_name(int fontno, environment *env) +{ + symbol f = font_table[fontno]->get_name(); + if (font_table[fontno]->is_style()) { + return concat(env->get_family()->nm, f); + } + return f; +} + hunits font_info::get_space_width(font_size fs, int space_size) { if (is_constant_spaced == CONSTANT_SPACE_NONE) @@ -626,14 +647,6 @@ inline int tfont::get_kern(charinfo *c1, charinfo *c2, hunits *res) } } -tfont *make_tfont(tfont_spec &spec) -{ - for (tfont *p = tfont::tfont_list; p; p = p->next) - if (*p == spec) - return p; - return new tfont(spec); -} - tfont *tfont::tfont_list = 0; tfont::tfont(tfont_spec &spec) : tfont_spec(spec) @@ -658,7 +671,7 @@ class real_output_file : public output_file { int piped; #endif int printing; // decision via optional page list - int output_on; // .output 1 or .output 0 requests + int output_on; // \O[0] or \O[1] escape calls virtual void really_transparent_char(unsigned char) = 0; virtual void really_print_line(hunits x, vunits y, node *n, vunits before, vunits after, hunits width) = 0; @@ -727,6 +740,8 @@ class troff_output_file : public real_output_file { int current_slant; int current_height; tfont *current_tfont; + color *current_fill_color; + color *current_glyph_color; int current_font_number; symbol *font_position; int nfont_positions; @@ -739,6 +754,7 @@ class troff_output_file : public real_output_file { void put(char c); void put(unsigned char c); void put(int i); + void put(unsigned int i); void put(const char *s); void set_font(tfont *tf); void flush_tbuf(); @@ -746,13 +762,13 @@ public: troff_output_file(); ~troff_output_file(); void trailer(vunits page_length); - void put_char(charinfo *ci, tfont *tf); - void put_char_width(charinfo *ci, tfont *tf, hunits w, hunits k); + void put_char(charinfo *, tfont *, color *, color *); + void put_char_width(charinfo *, tfont *, color *, color *, hunits, hunits); void right(hunits); void down(vunits); void moveto(hunits, vunits); - void start_special(tfont *tf, int no_init_string = 0); - void start_special(int no_init_string = 0); + void start_special(tfont *, color *, color *, int = 0); + void start_special(); void special_char(unsigned char c); void end_special(); void word_marker(); @@ -763,9 +779,11 @@ public: void really_put_filename(const char *filename); void really_on(); void really_off(); - void draw(char, hvpair *, int, font_size); + void draw(char, hvpair *, int, font_size, color *, color *); void determine_line_limits (char code, hvpair *point, int npoints); void check_charinfo(tfont *tf, charinfo *ci); + void glyph_color(color *c); + void fill_color(color *c); int get_hpos() { return hpos; } int get_vpos() { return vpos; } }; @@ -796,29 +814,29 @@ inline void troff_output_file::put(int i) put_string(i_to_a(i), fp); } -void troff_output_file::start_special(tfont *tf, int no_init_string) +inline void troff_output_file::put(unsigned int i) { - flush_tbuf(); + put_string(ui_to_a(i), fp); +} - /* - * 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); - } +void troff_output_file::start_special(tfont *tf, color *gcol, color *fcol, + int no_init_string) +{ + flush_tbuf(); do_motion(); + if (tf != current_tfont) + set_font(tf); + glyph_color(gcol); + fill_color(fcol); if (!no_init_string) put("x X "); } -void troff_output_file::start_special(int no_init_string) +void troff_output_file::start_special() { flush_tbuf(); do_motion(); - if (!no_init_string) - put("x X "); + put("x X "); } void troff_output_file::special_char(unsigned char c) @@ -844,8 +862,7 @@ void troff_output_file::really_print_line(hunits x, vunits y, node *n, { moveto(x, y); while (n != 0) { - if (is_on() || (n->force_tprint())) - n->tprint(this); + n->tprint(this); n = n->next; } flush_tbuf(); @@ -864,7 +881,8 @@ void troff_output_file::really_print_line(hunits x, vunits y, node *n, inline void troff_output_file::word_marker() { flush_tbuf(); - put('w'); + if (is_on()) + put('w'); } inline void troff_output_file::right(hunits n) @@ -920,6 +938,11 @@ void troff_output_file::do_motion() void troff_output_file::flush_tbuf() { + if (!is_on()) { + tbuf_len = 0; + return; + } + if (tbuf_len == 0) return; if (tbuf_kern == 0) @@ -930,7 +953,7 @@ void troff_output_file::flush_tbuf() put(' '); } check_output_limits(hpos, vpos); - check_output_limits(hpos, vpos + current_size + current_height); + check_output_limits(hpos, vpos - current_size); for (int i = 0; i < tbuf_len; i++) put(tbuf[i]); @@ -940,29 +963,37 @@ void troff_output_file::flush_tbuf() void troff_output_file::check_charinfo(tfont *tf, charinfo *ci) { - int size = tf->get_size().to_scaled_points(); + if (!is_on()) + return; + int height = tf->get_char_height(ci).to_units(); int width = tf->get_width(ci).to_units() + tf->get_italic_correction(ci).to_units(); int depth = tf->get_char_depth(ci).to_units(); - check_output_limits(output_hpos, - output_vpos - height); - check_output_limits(output_hpos + width, - output_vpos + size + depth); + check_output_limits(output_hpos, output_vpos - height); + check_output_limits(output_hpos + width, output_vpos + depth); } -void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, - hunits k) +void troff_output_file::put_char_width(charinfo *ci, tfont *tf, + color *gcol, color *fcol, + hunits w, hunits k) { + int kk = k.to_units(); + if (!is_on()) { + flush_tbuf(); + hpos += w.to_units() + kk; + return; + } if (tf != current_tfont) { flush_tbuf(); set_font(tf); } char c = ci->get_ascii_code(); - int kk = k.to_units(); if (c == '\0') { flush_tbuf(); do_motion(); + glyph_color(gcol); + fill_color(fcol); check_charinfo(tf, ci); if (ci->numbered()) { put('N'); @@ -983,6 +1014,7 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, } else if (tcommand_flag) { if (tbuf_len > 0 && hpos == output_hpos && vpos == output_vpos + && gcol == current_glyph_color && fcol == current_fill_color && kk == tbuf_kern && tbuf_len < TBUF_SIZE) { check_charinfo(tf, ci); @@ -993,6 +1025,8 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, } flush_tbuf(); do_motion(); + glyph_color(gcol); + fill_color(fcol); check_charinfo(tf, ci); tbuf[tbuf_len++] = c; output_hpos += w.to_units() + kk; @@ -1004,7 +1038,9 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, int n = hpos - output_hpos; check_charinfo(tf, ci); // check_output_limits(output_hpos, output_vpos); - if (vpos == output_vpos && n > 0 && n < 100 && !force_motion) { + if (vpos == output_vpos + && gcol == current_glyph_color && fcol == current_fill_color + && n > 0 && n < 100 && !force_motion) { put(char(n/10 + '0')); put(char(n%10 + '0')); put(c); @@ -1019,14 +1055,19 @@ void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w, } } -void troff_output_file::put_char(charinfo *ci, tfont *tf) +void troff_output_file::put_char(charinfo *ci, tfont *tf, + color *gcol, color *fcol) { flush_tbuf(); + if (!is_on()) + return; if (tf != current_tfont) set_font(tf); char c = ci->get_ascii_code(); if (c == '\0') { do_motion(); + glyph_color(gcol); + fill_color(fcol); if (ci->numbered()) { put('N'); put(ci->get_number()); @@ -1045,7 +1086,9 @@ void troff_output_file::put_char(charinfo *ci, tfont *tf) } else { int n = hpos - output_hpos; - if (vpos == output_vpos && n > 0 && n < 100) { + if (vpos == output_vpos + && gcol == current_glyph_color && fcol == current_fill_color + && n > 0 && n < 100) { put(char(n/10 + '0')); put(char(n%10 + '0')); put(c); @@ -1053,6 +1096,8 @@ void troff_output_file::put_char(charinfo *ci, tfont *tf) } else { do_motion(); + glyph_color(gcol); + fill_color(fcol); put('c'); put(c); } @@ -1115,12 +1160,112 @@ void troff_output_file::set_font(tfont *tf) current_tfont = tf; } +void troff_output_file::fill_color(color *col) +{ + if ((current_fill_color == col) || !color_flag) + return; + flush_tbuf(); + put("DF"); + unsigned int components[4]; + color_scheme cs; + cs = col->get_components(components); + switch (cs) { + case DEFAULT: + put('d'); + break; + case RGB: + put("r "); + put(Red); + put(' '); + put(Green); + put(' '); + put(Blue); + break; + case CMY: + put("c "); + put(Cyan); + put(' '); + put(Magenta); + put(' '); + put(Yellow); + break; + case CMYK: + put("k "); + put(Cyan); + put(' '); + put(Magenta); + put(' '); + put(Yellow); + put(' '); + put(Black); + break; + case GRAY: + put("g "); + put(Gray); + break; + } + put('\n'); + current_fill_color = col; +} + +void troff_output_file::glyph_color(color *col) +{ + if ((current_glyph_color == col) || !color_flag) + return; + flush_tbuf(); + put("m"); + unsigned int components[4]; + color_scheme cs; + cs = col->get_components(components); + switch (cs) { + case DEFAULT: + put('d'); + break; + case RGB: + put("r "); + put(Red); + put(' '); + put(Green); + put(' '); + put(Blue); + break; + case CMY: + put("c "); + put(Cyan); + put(' '); + put(Magenta); + put(' '); + put(Yellow); + break; + case CMYK: + put("k "); + put(Cyan); + put(' '); + put(Magenta); + put(' '); + put(Yellow); + put(' '); + put(Black); + break; + case GRAY: + put("g "); + put(Gray); + break; + } + put('\n'); + current_glyph_color = col; +} + // determine_line_limits - works out the smallest box which will contain // the entity, code, built from the point array. void troff_output_file::determine_line_limits(char code, hvpair *point, int npoints) { int i, x, y; + + if (!is_on()) + return; + switch (code) { case 'c': case 'C': @@ -1157,8 +1302,37 @@ void troff_output_file::determine_line_limits(char code, hvpair *point, check_output_limits(x, y); } break; + case 'a': + double c[2]; + int p[4]; + int minx, miny, maxx, maxy; + x = output_hpos; + y = output_vpos; + p[0] = point[0].h.to_units(); + p[1] = point[0].v.to_units(); + p[2] = point[1].h.to_units(); + p[3] = point[1].v.to_units(); + if (adjust_arc_center(p, c)) { + check_output_arc_limits(x, y, + p[0], p[1], p[2], p[3], + c[0], c[1], + &minx, &maxx, &miny, &maxy); + check_output_limits(minx, miny); + check_output_limits(maxx, maxy); + break; + } + // fall through + case 'l': + x = output_hpos; + y = output_vpos; + check_output_limits(x, y); + for (i = 0; i < npoints; i++) { + x += point[i].h.to_units(); + y += point[i].v.to_units(); + check_output_limits(x, y); + } + break; default: - // remember this doesn't work for arc.. yet x = output_hpos; y = output_vpos; for (i = 0; i < npoints; i++) { @@ -1170,34 +1344,37 @@ void troff_output_file::determine_line_limits(char code, hvpair *point, } void troff_output_file::draw(char code, hvpair *point, int npoints, - font_size fsize) + font_size fsize, color *gcol, color *fcol) { + int i; flush_tbuf(); do_motion(); - int size = fsize.to_scaled_points(); - if (current_size != size) { - put('s'); - put(size); - put('\n'); - current_size = size; - current_tfont = 0; - } - put('D'); - put(code); - int i; - if (code == 'c') { - put(' '); - put(point[0].h.to_units()); - } - else - for (i = 0; i < npoints; i++) { - put(' '); - put(point[i].h.to_units()); + glyph_color(gcol); + fill_color(fcol); + if (is_on()) { + int size = fsize.to_scaled_points(); + if (current_size != size) { + put('s'); + put(size); + put('\n'); + current_size = size; + current_tfont = 0; + } + put('D'); + put(code); + if (code == 'c') { put(' '); - put(point[i].v.to_units()); + put(point[0].h.to_units()); } - - determine_line_limits(code, point, npoints); + else + for (i = 0; i < npoints; i++) { + put(' '); + put(point[i].h.to_units()); + put(' '); + put(point[i].v.to_units()); + } + determine_line_limits(code, point, npoints); + } for (i = 0; i < npoints; i++) output_hpos += point[i].h.to_units(); @@ -1207,15 +1384,18 @@ void troff_output_file::draw(char code, hvpair *point, int npoints, output_vpos += point[i].v.to_units(); vpos = output_vpos; } - put('\n'); + if (is_on()) + put('\n'); } -void troff_output_file::really_on () +void troff_output_file::really_on() { flush_tbuf(); + force_motion = 1; + do_motion(); } -void troff_output_file::really_off () +void troff_output_file::really_off() { flush_tbuf(); } @@ -1412,7 +1592,7 @@ int real_output_file::is_printing() void real_output_file::begin_page(int pageno, vunits page_length) { printing = in_output_page_list(pageno); - if (printing && output_on) + if (printing) really_begin_page(pageno, page_length); } @@ -1454,9 +1634,8 @@ void real_output_file::really_put_filename(const char *filename) void real_output_file::on() { really_on(); - if (output_on == 0) { + if (output_on == 0) output_on = 1; - } } void real_output_file::off() @@ -1467,7 +1646,7 @@ void real_output_file::off() int real_output_file::is_on() { - return( output_on ); + return output_on; } void real_output_file::really_on() @@ -1562,14 +1741,16 @@ class glyph_node : public charinfo_node { static glyph_node *free_list; protected: tfont *tf; + color *gcol; + color *fcol; /* this is needed for grotty */ #ifdef STORE_WIDTH hunits wid; - glyph_node(charinfo *, tfont *, hunits, node * = 0); + glyph_node(charinfo *, tfont *, color *, color *, hunits, node * = 0); #endif public: void *operator new(size_t); void operator delete(void *); - glyph_node(charinfo *, tfont *, node * = 0); + glyph_node(charinfo *, tfont *, color *, color *, node * = 0); ~glyph_node() {} node *copy(); node *merge_glyph_node(glyph_node *); @@ -1584,6 +1765,8 @@ public: hunits skew(); hyphenation_type get_hyphenation_type(); tfont *get_tfont(); + color *get_glyph_color(); + color *get_fill_color(); void tprint(troff_output_file *); void zero_width_tprint(troff_output_file *); hyphen_list *get_hyphen_list(hyphen_list *ss = 0); @@ -1602,12 +1785,14 @@ class ligature_node : public glyph_node { node *n1; node *n2; #ifdef STORE_WIDTH - ligature_node(charinfo *, tfont *, hunits, node *gn1, node *gn2, node *x = 0); + ligature_node(charinfo *, tfont *, color *, color *, hunits, + node *, node *, node * = 0); #endif public: void *operator new(size_t); void operator delete(void *); - ligature_node(charinfo *, tfont *, node *gn1, node *gn2, node *x = 0); + ligature_node(charinfo *, tfont *, color *, color *, + node *, node *, node * = 0); ~ligature_node(); node *copy(); node *add_self(node *, hyphen_list **); @@ -1708,8 +1893,8 @@ void ligature_node::operator delete(void *p) delete[] (char *)p; } -glyph_node::glyph_node(charinfo *c, tfont *t, node *x) -: charinfo_node(c, x), tf(t) +glyph_node::glyph_node(charinfo *c, tfont *t, color *gc, color *fc, node *x) +: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc) { #ifdef STORE_WIDTH wid = tf->get_width(ci); @@ -1717,8 +1902,9 @@ glyph_node::glyph_node(charinfo *c, tfont *t, node *x) } #ifdef STORE_WIDTH -glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x) -: charinfo_node(c, x), tf(t), wid(w) +glyph_node::glyph_node(charinfo *c, tfont *t, + color *gc, color *fc, hunits w, node *x) +: charinfo_node(c, x), tf(t), gcol(gc), fcol(fc), wid(w) { } #endif @@ -1726,9 +1912,9 @@ glyph_node::glyph_node(charinfo *c, tfont *t, hunits w, node *x) node *glyph_node::copy() { #ifdef STORE_WIDTH - return new glyph_node(ci, tf, wid); + return new glyph_node(ci, tf, gcol, fcol, wid); #else - return new glyph_node(ci, tf); + return new glyph_node(ci, tf, gcol, fcol); #endif } @@ -1779,6 +1965,26 @@ tfont *glyph_node::get_tfont() return tf; } +color *node::get_glyph_color() +{ + return 0; +} + +color *glyph_node::get_glyph_color() +{ + return gcol; +} + +color *node::get_fill_color() +{ + return 0; +} + +color *glyph_node::get_fill_color() +{ + return fcol; +} + node *node::merge_glyph_node(glyph_node * /*gn*/) { return 0; @@ -1786,12 +1992,12 @@ node *node::merge_glyph_node(glyph_node * /*gn*/) node *glyph_node::merge_glyph_node(glyph_node *gn) { - if (tf == gn->tf) { + if (tf == gn->tf && gcol == gn->gcol && fcol == gn->fcol) { charinfo *lig; if ((lig = tf->get_lig(ci, gn->ci)) != 0) { node *next1 = next; next = 0; - return new ligature_node(lig, tf, this, gn, next1); + return new ligature_node(lig, tf, gcol, fcol, this, gn, next1); } hunits kern; if (tf->get_kern(ci, gn->ci, &kern)) { @@ -1860,16 +2066,16 @@ void glyph_node::ascii_print(ascii_output_file *ascii) ascii->outs(ci->nm.contents()); } -ligature_node::ligature_node(charinfo *c, tfont *t, +ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc, node *gn1, node *gn2, node *x) -: glyph_node(c, t, x), n1(gn1), n2(gn2) +: glyph_node(c, t, gc, fc, 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) +ligature_node::ligature_node(charinfo *c, tfont *t, color *gc, color *fc, + hunits w, node *gn1, node *gn2, node *x) +: glyph_node(c, t, gc, fc, w, x), n1(gn1), n2(gn2) { } #endif @@ -1883,9 +2089,9 @@ ligature_node::~ligature_node() node *ligature_node::copy() { #ifdef STORE_WIDTH - return new ligature_node(ci, tf, wid, n1->copy(), n2->copy()); + return new ligature_node(ci, tf, gcol, fcol, wid, n1->copy(), n2->copy()); #else - return new ligature_node(ci, tf, n1->copy(), n2->copy()); + return new ligature_node(ci, tf, gcol, fcol, n1->copy(), n2->copy()); #endif } @@ -1986,10 +2192,12 @@ node *kern_pair_node::add_discretionary_hyphen() tfont *tf = n2->get_tfont(); if (tf) { if (tf->contains(soft_hyphen_char)) { + color *gcol = n2->get_glyph_color(); + color *fcol = n2->get_fill_color(); node *next1 = next; next = 0; node *n = copy(); - glyph_node *gn = new glyph_node(soft_hyphen_char, tf); + glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol); node *nn = n->merge_glyph_node(gn); if (nn == 0) { gn->next = n; @@ -2121,10 +2329,12 @@ node *node::add_discretionary_hyphen() if (!tf) return new hyphen_inhibitor_node(this); if (tf->contains(soft_hyphen_char)) { + color *gcol = get_glyph_color(); + color *fcol = get_fill_color(); node *next1 = next; next = 0; node *n = copy(); - glyph_node *gn = new glyph_node(soft_hyphen_char, tf); + glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol); node *n1 = n->merge_glyph_node(gn); if (n1 == 0) { gn->next = n; @@ -2362,8 +2572,9 @@ int italic_corrected_node::character_type() class break_char_node : public node { node *ch; char break_code; + color *col; public: - break_char_node(node *, int, node * = 0); + break_char_node(node *, int, color *, node * = 0); ~break_char_node(); node *copy(); hunits width(); @@ -2387,8 +2598,8 @@ public: int force_tprint(); }; -break_char_node::break_char_node(node *n, int c, node *x) -: node(x), ch(n), break_code(c) +break_char_node::break_char_node(node *n, int bc, color *c, node *x) +: node(x), ch(n), break_code(bc), col(c) { } @@ -2399,7 +2610,7 @@ break_char_node::~break_char_node() node *break_char_node::copy() { - return new break_char_node(ch->copy(), break_code); + return new break_char_node(ch->copy(), break_code, col); } hunits break_char_node::width() @@ -2431,13 +2642,13 @@ node *break_char_node::add_self(node *n, hyphen_list **p) { assert((*p)->hyphenation_code == 0); if ((*p)->breakable && (break_code & 1)) { - n = new space_node(H0, n); + n = new space_node(H0, col, n); n->freeze_space(); } next = n; n = this; if ((*p)->breakable && (break_code & 2)) { - n = new space_node(H0, n); + n = new space_node(H0, col, n); n->freeze_space(); } hyphen_list *pp = *p; @@ -2493,17 +2704,17 @@ node *vertical_size_node::copy() node *hmotion_node::copy() { - return new hmotion_node(n, was_tab, unformat); + return new hmotion_node(n, was_tab, unformat, col); } node *space_char_hmotion_node::copy() { - return new space_char_hmotion_node(n); + return new space_char_hmotion_node(n, col); } node *vmotion_node::copy() { - return new vmotion_node(n); + return new vmotion_node(n, col); } node *dummy_node::copy() @@ -2648,6 +2859,8 @@ node *bracket_node::copy() bracket_node *on = new bracket_node; node *last = 0; node *tem; + if (list) + list->last = 0; for (tem = list; tem; tem = tem->next) { if (tem->next) tem->next->last = tem; @@ -2711,13 +2924,13 @@ inline void space_node::operator delete(void *p) } #endif -space_node::space_node(hunits nn, node *p) -: node(p), n(nn), set(0), was_escape_colon(0) +space_node::space_node(hunits nn, color *c, node *p) +: node(p), n(nn), set(0), was_escape_colon(0), col(c) { } -space_node::space_node(hunits nn, int s, int flag, node *p) -: node(p), n(nn), set(s), was_escape_colon(flag) +space_node::space_node(hunits nn, int s, int flag, color *c, node *p) +: node(p), n(nn), set(s), was_escape_colon(flag), col(c) { } @@ -2729,7 +2942,7 @@ space_node::~space_node() node *space_node::copy() { - return new space_node(n, set, was_escape_colon); + return new space_node(n, set, was_escape_colon, col); } int space_node::force_tprint() @@ -3025,7 +3238,9 @@ void node::asciify(macro *m) void glyph_node::asciify(macro *m) { - unsigned char c = ci->get_ascii_code(); + unsigned char c = ci->get_asciify_code(); + if (c == 0) + c = ci->get_ascii_code(); if (c != 0) { m->append(c); delete this; @@ -3098,8 +3313,9 @@ void hmotion_node::asciify(macro *m) m->append(this); } -space_char_hmotion_node::space_char_hmotion_node(hunits i, node *next) -: hmotion_node(i, next) +space_char_hmotion_node::space_char_hmotion_node(hunits i, color *c, + node *next) +: hmotion_node(i, c, next) { } @@ -3153,8 +3369,8 @@ int node::nbreaks() return 0; } -breakpoint *space_node::get_breakpoints(hunits width, int ns, breakpoint *rest, - int is_inner) +breakpoint *space_node::get_breakpoints(hunits width, int ns, + breakpoint *rest, int is_inner) { if (next->discardable()) return rest; @@ -3351,23 +3567,27 @@ special_node::special_node(const macro &m, int n) 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); + int fontno = env_definite_font(curenv); + tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fontno); if (curenv->is_composite()) tf = tf->get_plain(); + gcol = curenv->get_glyph_color(); + fcol = curenv->get_fill_color(); } -special_node::special_node(const macro &m, tfont *t, int n) -: mac(m), tf(t), no_init_string(n) +special_node::special_node(const macro &m, tfont *t, + color *gc, color *fc, int n) +: mac(m), tf(t), gcol(gc), fcol(fc), no_init_string(n) { } int special_node::same(node *n) { - return ((mac == ((special_node *)n)->mac) - && (tf == ((special_node *)n)->tf) - && (no_init_string == ((special_node *)n)->no_init_string)); + return mac == ((special_node *)n)->mac + && tf == ((special_node *)n)->tf + && gcol == ((special_node *)n)->gcol + && fcol == ((special_node *)n)->fcol + && no_init_string == ((special_node *)n)->no_init_string; } const char *special_node::type() @@ -3387,12 +3607,12 @@ int special_node::force_tprint() node *special_node::copy() { - return new special_node(mac, tf, no_init_string); + return new special_node(mac, tf, gcol, fcol, no_init_string); } void special_node::tprint_start(troff_output_file *out) { - out->start_special(get_tfont(), no_init_string); + out->start_special(tf, gcol, fcol, no_init_string); } void special_node::tprint_char(troff_output_file *out, unsigned char c) @@ -3413,18 +3633,20 @@ tfont *special_node::get_tfont() /* 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) +: is_on(on_or_off), emit_limits(issue_limits), + filename(0), position(0), image_id(0) { } -suppress_node::suppress_node(symbol f, char p) -: is_on(2), emit_limits(0), filename(f), position(p) +suppress_node::suppress_node(symbol f, char p, int id) +: is_on(2), emit_limits(0), filename(f), position(p), image_id(id) { } 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) + symbol f, char p, int id) +: is_on(on_or_off), emit_limits(issue_limits), + filename(f), position(p), image_id(id) { } @@ -3433,8 +3655,8 @@ 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)); -; + && (position == ((suppress_node *)n)->position) + && (image_id == ((suppress_node *)n)->image_id)); } const char *suppress_node::type() @@ -3444,7 +3666,7 @@ const char *suppress_node::type() node *suppress_node::copy() { - return new suppress_node(emit_limits, is_on, filename, position); + return new suppress_node(emit_limits, is_on, filename, position, image_id); } int get_reg_int(const char *p) @@ -3483,6 +3705,7 @@ void suppress_node::put(troff_output_file *out, const char *s) static char last_position = 0; static const char *last_image_filename = 0; +static int last_image_id = 0; inline int min(int a, int b) { @@ -3508,22 +3731,23 @@ inline int min(int a, int b) void suppress_node::tprint(troff_output_file *out) { - int current_page = get_reg_int("%"); + int current_page = topdiv->get_page_number(); // 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(); + last_image_filename = strdup(filename.contents()); + last_image_id = image_id; + // printf("start of image and page = %d\n", current_page); } 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); + // last_image_id is placed + sprintf(name, last_image_filename, last_image_id); if (is_html) { switch (last_position) { case 'c': @@ -3551,14 +3775,18 @@ void suppress_node::tprint(troff_output_file *out) } else { // postscript (or other device) - if (current_page != suppress_start_page) + if (suppress_start_page > 0 && current_page != suppress_start_page) error("suppression limit registers span more than one page;\n" "image description %1 will be wrong", image_no); + // if (topdiv->get_page_number() != suppress_start_page) + // fprintf(stderr, "end of image and topdiv page = %d and suppress_start_page = %d\n", + // topdiv->get_page_number(), suppress_start_page); + // 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, + topdiv->get_page_number(), get_reg_int("opminx"), get_reg_int("opminy"), get_reg_int("opmaxx"), get_reg_int("opmaxy"), // page offset + line length @@ -3568,12 +3796,13 @@ void suppress_node::tprint(troff_output_file *out) } } else { - if (is_on) + if (is_on) { out->on(); + // lastly we reset the output registers + reset_output_registers(out->get_vpos()); + } else out->off(); - // lastly we reset the output registers - reset_output_registers(out->get_vpos()); suppress_start_page = current_page; } } @@ -3670,7 +3899,9 @@ hyphenation_type composite_node::get_hyphenation_type() void composite_node::asciify(macro *m) { - unsigned char c = ci->get_ascii_code(); + unsigned char c = ci->get_asciify_code(); + if (c == 0) + c = ci->get_ascii_code(); if (c != 0) { m->append(c); delete this; @@ -3741,14 +3972,14 @@ width_list::width_list(width_list *w) { } -word_space_node::word_space_node(hunits d, width_list *w, node *x) -: space_node(d, x), orig_width(w), unformat(0) +word_space_node::word_space_node(hunits d, color *c, width_list *w, node *x) +: space_node(d, c, x), orig_width(w), unformat(0) { } -word_space_node::word_space_node(hunits d, int s, width_list *w, +word_space_node::word_space_node(hunits d, int s, color *c, width_list *w, int flag, node *x) -: space_node(d, s, 0, x), orig_width(w), unformat(flag) +: space_node(d, s, 0, c, x), orig_width(w), unformat(flag) { } @@ -3774,7 +4005,7 @@ node *word_space_node::copy() w_new_curr = w_new_curr->next; w_old_curr = w_old_curr->next; } - return new word_space_node(n, set, w_new, unformat); + return new word_space_node(n, set, col, w_new, unformat); } int word_space_node::set_unformat_flag() @@ -3785,8 +4016,9 @@ int word_space_node::set_unformat_flag() void word_space_node::tprint(troff_output_file *out) { + out->fill_color(col); out->word_marker(); - space_node::tprint(out); + out->right(n); } int word_space_node::merge_space(hunits h, hunits sw, hunits ssw) @@ -3800,19 +4032,20 @@ int word_space_node::merge_space(hunits h, hunits sw, hunits ssw) return 1; } -unbreakable_space_node::unbreakable_space_node(hunits d, node *x) -: word_space_node(d, 0, x) +unbreakable_space_node::unbreakable_space_node(hunits d, color *c, node *x) +: word_space_node(d, c, 0, x) { } -unbreakable_space_node::unbreakable_space_node(hunits d, int s, node *x) -: word_space_node(d, s, 0, 0, x) +unbreakable_space_node::unbreakable_space_node(hunits d, int s, + color *c, node *x) +: word_space_node(d, s, c, 0, 0, x) { } node *unbreakable_space_node::copy() { - return new unbreakable_space_node(n, set); + return new unbreakable_space_node(n, set, col); } int unbreakable_space_node::force_tprint() @@ -3845,8 +4078,9 @@ hvpair::hvpair() { } -draw_node::draw_node(char c, hvpair *p, int np, font_size s) -: npoints(np), sz(s), code(c) +draw_node::draw_node(char c, hvpair *p, int np, font_size s, + color *gc, color *fc) +: npoints(np), sz(s), gcol(gc), fcol(fc), code(c) { point = new hvpair[npoints]; for (int i = 0; i < npoints; i++) @@ -3856,7 +4090,8 @@ draw_node::draw_node(char c, hvpair *p, int np, font_size s) int draw_node::same(node *n) { draw_node *nd = (draw_node *)n; - if (code != nd->code || npoints != nd->npoints || sz != nd->sz) + if (code != nd->code || npoints != nd->npoints || sz != nd->sz + || gcol != nd->gcol || fcol != nd->fcol) return 0; for (int i = 0; i < npoints; i++) if (point[i].h != nd->point[i].h || point[i].v != nd->point[i].v) @@ -3900,12 +4135,12 @@ vunits draw_node::vertical_width() node *draw_node::copy() { - return new draw_node(code, point, npoints, sz); + return new draw_node(code, point, npoints, sz, gcol, fcol); } void draw_node::tprint(troff_output_file *out) { - out->draw(code, point, npoints, sz); + out->draw(code, point, npoints, sz, gcol, fcol); } /* tprint methods */ @@ -3914,7 +4149,7 @@ void glyph_node::tprint(troff_output_file *out) { tfont *ptf = tf->get_plain(); if (ptf == tf) - out->put_char_width(ci, ptf, width(), H0); + out->put_char_width(ci, ptf, gcol, fcol, width(), H0); else { hunits offset; int bold = tf->get_bold(&offset); @@ -3933,10 +4168,10 @@ void glyph_node::tprint(troff_output_file *out) else k = tf->get_track_kern(); if (bold) { - out->put_char(ci, ptf); + out->put_char(ci, ptf, gcol, fcol); out->right(offset); } - out->put_char_width(ci, ptf, w, k); + out->put_char_width(ci, ptf, gcol, fcol, w, k); } } @@ -3954,10 +4189,10 @@ void glyph_node::zero_width_tprint(troff_output_file *out) x = x/2; out->right(x); } - out->put_char(ci, ptf); + out->put_char(ci, ptf, gcol, fcol); if (bold) { out->right(offset); - out->put_char(ci, ptf); + out->put_char(ci, ptf, gcol, fcol); out->right(-offset); } if (cs) @@ -3995,20 +4230,23 @@ void hline_node::tprint(troff_output_file *out) hunits xx = x - w; hunits xx2 = xx/2; out->right(xx2); - n->tprint(out); + if (out->is_on()) + n->tprint(out); out->right(xx - xx2); } else { hunits rem = x - w*i; if (rem > H0) if (n->overlaps_horizontally()) { - n->tprint(out); + if (out->is_on()) + n->tprint(out); out->right(rem - w); } else out->right(rem); while (--i >= 0) - n->tprint(out); + if (out->is_on()) + n->tprint(out); } } @@ -4037,11 +4275,13 @@ void vline_node::tprint(troff_output_file *out) if (overlaps) { n->zero_width_tprint(out); out->down(-rem); - n->tprint(out); + if (out->is_on()) + n->tprint(out); out->down(-h); } else { - n->tprint(out); + if (out->is_on()) + n->tprint(out); out->down(-h - rem); } } @@ -4062,7 +4302,8 @@ void vline_node::tprint(troff_output_file *out) n->zero_width_tprint(out); out->down(h); } - n->tprint(out); + if (out->is_on()) + n->tprint(out); } } } @@ -4131,16 +4372,19 @@ void node::zero_width_tprint(troff_output_file *out) void space_node::tprint(troff_output_file *out) { + out->fill_color(col); out->right(n); } void hmotion_node::tprint(troff_output_file *out) { + out->fill_color(col); out->right(n); } void vmotion_node::tprint(troff_output_file *out) { + out->fill_color(col); out->down(n); } @@ -4226,6 +4470,8 @@ node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0) int fn = fontno; int found = font_table[fontno]->contains(s); if (!found) { + if (s->is_fallback()) + return make_composite_node(s, env); if (s->numbered()) { if (!no_error_message) warning(WARN_CHAR, "can't find numbered character %1", @@ -4284,16 +4530,20 @@ node *make_glyph_node(charinfo *s, environment *env, int no_error_message = 0) tfont *tf = font_table[fontno]->get_tfont(fs, char_height, char_slant, fn); if (env->is_composite()) tf = tf->get_plain(); - return new glyph_node(s, tf); + color *gcol = env->get_glyph_color(); + color *fcol = env->get_fill_color(); + return new glyph_node(s, tf, gcol, fcol); } node *make_node(charinfo *ci, environment *env) { switch (ci->get_special_translation()) { case charinfo::TRANSLATE_SPACE: - return new space_char_hmotion_node(env->get_space_width()); + return new space_char_hmotion_node(env->get_space_width(), + env->get_fill_color()); case charinfo::TRANSLATE_STRETCHABLE_SPACE: - return new unbreakable_space_node(env->get_space_width()); + return new unbreakable_space_node(env->get_space_width(), + env->get_fill_color()); case charinfo::TRANSLATE_DUMMY: return new dummy_node; case charinfo::TRANSLATE_HYPHEN_INDICATOR: @@ -4304,7 +4554,7 @@ node *make_node(charinfo *ci, environment *env) if (tem) ci = tem; macro *mac = ci->get_macro(); - if (mac) + if (mac && !ci->is_fallback()) return make_composite_node(ci, env); else return make_glyph_node(ci, env); @@ -4333,11 +4583,14 @@ node *node::add_char(charinfo *ci, environment *env, node *res; switch (ci->get_special_translation()) { case charinfo::TRANSLATE_SPACE: - res = new space_char_hmotion_node(env->get_space_width(), this); + res = new space_char_hmotion_node(env->get_space_width(), + env->get_fill_color(), this); *widthp += res->width(); return res; case charinfo::TRANSLATE_STRETCHABLE_SPACE: - res = new unbreakable_space_node(env->get_space_width(), this); + res = new unbreakable_space_node(env->get_space_width(), + env->get_fill_color(), this); + res->freeze_space(); *widthp += res->width(); *spacep += res->nspaces(); return res; @@ -4350,7 +4603,7 @@ node *node::add_char(charinfo *ci, environment *env, if (tem) ci = tem; macro *mac = ci->get_macro(); - if (mac) { + if (mac && !ci->is_fallback()) { res = make_composite_node(ci, env); if (res) { res->next = this; @@ -4385,7 +4638,7 @@ node *node::add_char(charinfo *ci, environment *env, if (break_code) { node *next1 = res->next; res->next = 0; - res = new break_char_node(res, break_code, next1); + res = new break_char_node(res, break_code, env->get_fill_color(), next1); } return res; } @@ -4453,7 +4706,8 @@ int vertical_size_node::force_tprint() int hmotion_node::same(node *nd) { - return n == ((hmotion_node *)nd)->n; + return n == ((hmotion_node *)nd)->n + && col == ((hmotion_node *)nd)->col; } const char *hmotion_node::type() @@ -4488,7 +4742,8 @@ hyphen_list *hmotion_node::get_hyphen_list(hyphen_list *tail) int space_char_hmotion_node::same(node *nd) { - return n == ((space_char_hmotion_node *)nd)->n; + return n == ((space_char_hmotion_node *)nd)->n + && col == ((space_char_hmotion_node *)nd)->col; } const char *space_char_hmotion_node::type() @@ -4517,7 +4772,8 @@ hyphen_list *space_char_hmotion_node::get_hyphen_list(hyphen_list *tail) int vmotion_node::same(node *nd) { - return n == ((vmotion_node *)nd)->n; + return n == ((vmotion_node *)nd)->n + && col == ((vmotion_node *)nd)->col; } const char *vmotion_node::type() @@ -4841,7 +5097,10 @@ int composite_node::force_tprint() int glyph_node::same(node *nd) { - return ci == ((glyph_node *)nd)->ci && tf == ((glyph_node *)nd)->tf; + return ci == ((glyph_node *)nd)->ci + && tf == ((glyph_node *)nd)->tf + && gcol == ((glyph_node *)nd)->gcol + && fcol == ((glyph_node *)nd)->fcol; } const char *glyph_node::type() @@ -4907,8 +5166,9 @@ int dbreak_node::force_tprint() int break_char_node::same(node *nd) { - return (break_code == ((break_char_node *)nd)->break_code - && same_node(ch, ((break_char_node *)nd)->ch)); + return break_code == ((break_char_node *)nd)->break_code + && col == ((break_char_node *)nd)->col + && same_node(ch, ((break_char_node *)nd)->ch); } const char *break_char_node::type() @@ -4938,7 +5198,9 @@ int line_start_node::force_tprint() int space_node::same(node *nd) { - return n == ((space_node *)nd)->n && set == ((space_node *)nd)->set; + return n == ((space_node *)nd)->n + && set == ((space_node *)nd)->set + && col == ((space_node *)nd)->col; } const char *space_node::type() @@ -4948,8 +5210,9 @@ const char *space_node::type() int word_space_node::same(node *nd) { - return (n == ((word_space_node *)nd)->n - && set == ((word_space_node *)nd)->set); + return n == ((word_space_node *)nd)->n + && set == ((word_space_node *)nd)->set + && col == ((word_space_node *)nd)->col; } const char *word_space_node::type() @@ -4964,8 +5227,9 @@ int word_space_node::force_tprint() int unbreakable_space_node::same(node *nd) { - return (n == ((unbreakable_space_node *)nd)->n - && set == ((unbreakable_space_node *)nd)->set); + return n == ((unbreakable_space_node *)nd)->n + && set == ((unbreakable_space_node *)nd)->set + && col == ((unbreakable_space_node *)nd)->col; } const char *unbreakable_space_node::type() @@ -5345,7 +5609,7 @@ int symbol_fontno(symbol s) int is_good_fontno(int n) { - return n >= 0 && n < font_table_size && font_table[n] != NULL; + return n >= 0 && n < font_table_size && font_table[n] != 0; } int get_bold_fontno(int n) |