diff options
Diffstat (limited to 'contrib/groff/src/devices/grotty/tty.cpp')
-rw-r--r-- | contrib/groff/src/devices/grotty/tty.cpp | 242 |
1 files changed, 167 insertions, 75 deletions
diff --git a/contrib/groff/src/devices/grotty/tty.cpp b/contrib/groff/src/devices/grotty/tty.cpp index 812ebf826496..a959461f922a 100644 --- a/contrib/groff/src/devices/grotty/tty.cpp +++ b/contrib/groff/src/devices/grotty/tty.cpp @@ -1,5 +1,6 @@ // -*- C++ -*- -/* Copyright (C) 1989-2000, 2001, 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) This file is part of groff. @@ -16,14 +17,16 @@ 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "driver.h" #include "device.h" #include "ptable.h" -declare_ptable(char) -implement_ptable(char) +typedef signed char schar; + +declare_ptable(schar) +implement_ptable(schar) extern "C" const char *Version_string; @@ -41,25 +44,38 @@ extern "C" const char *Version_string; static int horizontal_tab_flag = 0; static int form_feed_flag = 0; -static int bold_flag = 1; -static int underline_flag = 1; +static int bold_flag_option = 1; +static int bold_flag; +static int underline_flag_option = 1; +static int underline_flag; static int overstrike_flag = 1; static int draw_flag = 1; -static int italic_flag = 0; -static int reverse_flag = 0; +static int italic_flag_option = 0; +static int italic_flag; +static int reverse_flag_option = 0; +static int reverse_flag; static int old_drawing_scheme = 0; +static void update_options(); +static void usage(FILE *stream); + +static int hline_char = '-'; +static int vline_char = '|'; + enum { UNDERLINE_MODE = 0x01, BOLD_MODE = 0x02, VDRAW_MODE = 0x04, HDRAW_MODE = 0x08, CU_MODE = 0x10, - COLOR_CHANGE = 0x20 + COLOR_CHANGE = 0x20, + START_LINE = 0x40, + END_LINE = 0x80 }; // Mode to use for bold-underlining. -static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; +static unsigned char bold_underline_mode_option = BOLD_MODE|UNDERLINE_MODE; +static unsigned char bold_underline_mode; #ifndef IS_EBCDIC_HOST #define CSI "\033[" @@ -77,7 +93,7 @@ static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; #define SGR_REVERSE CSI "7m" #define SGR_NO_REVERSE CSI "27m" // many terminals can't handle `CSI 39 m' and `CSI 49 m' to reset -// the foreground and bachground color, respectively; thus we use +// the foreground and background color, respectively; we thus use // `CSI 0 m' exclusively #define SGR_DEFAULT CSI "0m" @@ -105,13 +121,14 @@ tty_font *tty_font::load_tty_font(const char *s) const char *num = f->get_internal_name(); long n; if (num != 0 && (n = strtol(num, 0, 0)) != 0) - f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE)); + f->mode = (unsigned char)(n & (BOLD_MODE|UNDERLINE_MODE)); if (!underline_flag) f->mode &= ~UNDERLINE_MODE; if (!bold_flag) f->mode &= ~BOLD_MODE; if ((f->mode & (BOLD_MODE|UNDERLINE_MODE)) == (BOLD_MODE|UNDERLINE_MODE)) - f->mode = (f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) | bold_underline_mode; + f->mode = (unsigned char)((f->mode & ~(BOLD_MODE|UNDERLINE_MODE)) + | bold_underline_mode); return f; } @@ -138,11 +155,12 @@ class glyph { static glyph *free_list; public: glyph *next; - short hpos; + int w; + int hpos; unsigned int code; unsigned char mode; - char back_color_idx; - char fore_color_idx; + schar back_color_idx; + schar fore_color_idx; void *operator new(size_t); void operator delete(void *); inline int draw_mode() { return mode & (VDRAW_MODE|HDRAW_MODE); } @@ -181,19 +199,19 @@ class tty_printer : public printer { int nlines; int cached_v; int cached_vpos; - char curr_fore_idx; - char curr_back_idx; + schar curr_fore_idx; + schar curr_back_idx; int is_underline; int is_bold; int cu_flag; - PTABLE(char) tty_colors; - void make_underline(); - void make_bold(unsigned int); - char color_to_idx(color *col); - void add_char(unsigned int, int, int, color *, color *, unsigned char); + PTABLE(schar) tty_colors; + void make_underline(int); + void make_bold(unsigned int, int); + schar color_to_idx(color *col); + void add_char(unsigned int, int, int, int, color *, color *, unsigned char); char *make_rgb_string(unsigned int, unsigned int, unsigned int); - int tty_color(unsigned int, unsigned int, unsigned int, char *, - char = DEFAULT_COLOR_IDX); + int tty_color(unsigned int, unsigned int, unsigned int, schar *, + schar = DEFAULT_COLOR_IDX); public: tty_printer(const char *device); ~tty_printer(); @@ -203,7 +221,7 @@ public: void change_color(const environment * const env); void change_fill_color(const environment * const env); void put_char(unsigned int); - void put_color(char, int); + void put_color(schar, int); void begin_page(int) { } void end_page(int page_length); font *make_font(const char *); @@ -233,14 +251,14 @@ char *tty_printer::make_rgb_string(unsigned int r, int tty_printer::tty_color(unsigned int r, unsigned int g, - unsigned int b, char *idx, char value) + unsigned int b, schar *idx, schar value) { int unknown_color = 0; char *s = make_rgb_string(r, g, b); - char *i = tty_colors.lookup(s); + schar *i = tty_colors.lookup(s); if (!i) { unknown_color = 1; - i = new char[1]; + i = new schar[1]; *i = value; tty_colors.define(s, i); } @@ -249,10 +267,14 @@ int tty_printer::tty_color(unsigned int r, return unknown_color; } -tty_printer::tty_printer(const char *device) : cached_v(0) +tty_printer::tty_printer(const char *dev) : cached_v(0) { - is_utf8 = !strcmp(device, "utf8"); - char dummy; + is_utf8 = !strcmp(dev, "utf8"); + if (is_utf8) { + hline_char = 0x2500; + vline_char = 0x2502; + } + schar dummy; // black, white (void)tty_color(0, 0, 0, &dummy, 0); (void)tty_color(color::MAX_COLOR_VAL, @@ -278,11 +300,18 @@ tty_printer::~tty_printer() a_delete lines; } -void tty_printer::make_underline() +void tty_printer::make_underline(int w) { if (old_drawing_scheme) { - putchar('_'); - putchar('\b'); + if (!w) + warning("can't underline zero-width character"); + else { + int n = w / font::hor; + for (int i = 0; i < n; i++) + putchar('_'); + for (int j = 0; j < n; j++) + putchar('\b'); + } } else { if (!is_underline) { @@ -297,11 +326,17 @@ void tty_printer::make_underline() } } -void tty_printer::make_bold(unsigned int c) +void tty_printer::make_bold(unsigned int c, int w) { if (old_drawing_scheme) { - put_char(c); - putchar('\b'); + if (!w) + warning("can't print zero-width character in bold"); + else { + int n = w / font::hor; + put_char(c); + for (int i = 0; i < n; i++) + putchar('\b'); + } } else { if (!is_bold) @@ -310,13 +345,13 @@ void tty_printer::make_bold(unsigned int c) } } -char tty_printer::color_to_idx(color *col) +schar tty_printer::color_to_idx(color *col) { if (col->is_default()) return DEFAULT_COLOR_IDX; unsigned int r, g, b; col->get_rgb(&r, &g, &b); - char idx; + schar idx; if (tty_color(r, g, b, &idx)) { char *s = col->print_color(); error("Unknown color (%1) mapped to default", s); @@ -328,15 +363,15 @@ char tty_printer::color_to_idx(color *col) void tty_printer::set_char(int i, font *f, const environment *env, int w, const char *) { - if (w != font::hor) - fatal("width of character not equal to horizontal resolution"); - add_char(f->get_code(i), + if (w % font::hor != 0) + fatal("width of character not a multiple of horizontal resolution"); + add_char(f->get_code(i), w, env->hpos, env->vpos, env->col, env->fill, ((tty_font *)f)->get_mode()); } -void tty_printer::add_char(unsigned int c, +void tty_printer::add_char(unsigned int c, int w, int h, int v, color *fore, color *back, unsigned char mode) @@ -377,6 +412,7 @@ void tty_printer::add_char(unsigned int c, cached_vpos = vpos; } glyph *g = new glyph; + g->w = w; g->hpos = hpos; g->code = c; g->fore_color_idx = color_to_idx(fore); @@ -400,7 +436,8 @@ void tty_printer::add_char(unsigned int c, void tty_printer::special(char *arg, const environment *env, char type) { if (type == 'u') { - add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE); + add_char(*arg - '0', 0, env->hpos, env->vpos, env->col, env->fill, + CU_MODE); return; } if (type != 'p') @@ -433,17 +470,18 @@ void tty_printer::special(char *arg, const environment *env, char type) old_drawing_scheme = 1; else old_drawing_scheme = 0; + update_options(); } } void tty_printer::change_color(const environment * const env) { - add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); + add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); } void tty_printer::change_fill_color(const environment * const env) { - add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); + add_char(0, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE); } void tty_printer::draw(int code, int *p, int np, const environment *env) @@ -462,10 +500,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env) v += len; len = -len; } - while (len >= 0) { - add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE); + if (len >= 0 && len <= font::vert) + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE|END_LINE); + else { + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE); len -= font::vert; v += font::vert; + while (len > 0) { + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|START_LINE|END_LINE); + len -= font::vert; + v += font::vert; + } + add_char(vline_char, font::hor, env->hpos, v, env->col, env->fill, + VDRAW_MODE|END_LINE); } } if (p[1] == 0) { @@ -476,10 +526,22 @@ void tty_printer::draw(int code, int *p, int np, const environment *env) h += len; len = -len; } - while (len >= 0) { - add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE); + if (len >= 0 && len <= font::hor) + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE|END_LINE); + else { + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE); len -= font::hor; h += font::hor; + while (len > 0) { + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|START_LINE|END_LINE); + len -= font::hor; + h += font::hor; + } + add_char(hline_char, font::hor, h, env->vpos, env->col, env->fill, + HDRAW_MODE|END_LINE); } } } @@ -511,7 +573,7 @@ void tty_printer::put_char(unsigned int wc) putchar(wc); } -void tty_printer::put_color(char color_index, int back) +void tty_printer::put_color(schar color_index, int back) { if (color_index == DEFAULT_COLOR_IDX) { putstring(SGR_DEFAULT); @@ -541,6 +603,20 @@ void tty_printer::put_color(char color_index, int back) } } +// The possible Unicode combinations for crossing characters. +// +// ` ' = 0, ` -' = 4, `- ' = 8, `--' = 12, +// +// ` ' = 0, ` ' = 1, `|' = 2, `|' = 3 +// | | + +static int crossings[4*4] = { + 0x0000, 0x2577, 0x2575, 0x2502, + 0x2576, 0x250C, 0x2514, 0x251C, + 0x2574, 0x2510, 0x2518, 0x2524, + 0x2500, 0x252C, 0x2534, 0x253C +}; + void tty_printer::end_page(int page_length) { if (page_length % font::vert != 0) @@ -588,7 +664,12 @@ void tty_printer::end_page(int page_length) if (nextp && p->hpos == nextp->hpos) { if (p->draw_mode() == HDRAW_MODE && nextp->draw_mode() == VDRAW_MODE) { - nextp->code = '+'; + if (is_utf8) + nextp->code = + crossings[((p->mode & (START_LINE|END_LINE)) >> 4) + + ((nextp->mode & (START_LINE|END_LINE)) >> 6)]; + else + nextp->code = '+'; continue; } if (p->draw_mode() != 0 && p->draw_mode() == nextp->draw_mode()) { @@ -611,7 +692,7 @@ void tty_printer::end_page(int page_length) if (next_tab_pos > p->hpos) break; if (cu_flag) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -627,7 +708,7 @@ void tty_printer::end_page(int page_length) } for (; hpos < p->hpos; hpos++) { if (cu_flag) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -655,7 +736,7 @@ void tty_printer::end_page(int page_length) continue; } if (p->mode & UNDERLINE_MODE) - make_underline(); + make_underline(p->w); else if (!old_drawing_scheme && is_underline) { if (italic_flag) putstring(SGR_NO_ITALIC); @@ -666,7 +747,7 @@ void tty_printer::end_page(int page_length) is_underline = 0; } if (p->mode & BOLD_MODE) - make_bold(p->code); + make_bold(p->code, p->w); else if (!old_drawing_scheme && is_bold) { putstring(SGR_NO_BOLD); is_bold = 0; @@ -682,7 +763,7 @@ void tty_printer::end_page(int page_length) } } put_char(p->code); - hpos++; + hpos += p->w / font::hor; } if (!old_drawing_scheme && (is_bold || is_underline @@ -711,7 +792,23 @@ printer *make_printer() return new tty_printer(device); } -static void usage(FILE *stream); +static void update_options() +{ + if (old_drawing_scheme) { + italic_flag = 0; + reverse_flag = 0; + bold_underline_mode = bold_underline_mode_option; + bold_flag = bold_flag_option; + underline_flag = underline_flag_option; + } + else { + italic_flag = italic_flag_option; + reverse_flag = reverse_flag_option; + bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; + bold_flag = 1; + underline_flag = 1; + } +} int main(int argc, char **argv) { @@ -726,7 +823,7 @@ int main(int argc, char **argv) { "version", no_argument, 0, 'v' }, { NULL, 0, 0, 0 } }; - while ((c = getopt_long(argc, argv, "bBcdfF:hioruUv", long_options, NULL)) + while ((c = getopt_long(argc, argv, "bBcdfF:hiI:oruUv", long_options, NULL)) != EOF) switch(c) { case 'v': @@ -735,11 +832,14 @@ int main(int argc, char **argv) break; case 'i': // Use italic font instead of underlining. - italic_flag = 1; + italic_flag_option = 1; + break; + case 'I': + // ignore include search path break; case 'b': // Do not embolden by overstriking. - bold_flag = 0; + bold_flag_option = 0; break; case 'c': // Use old scheme for emboldening and underline. @@ -747,7 +847,7 @@ int main(int argc, char **argv) break; case 'u': // Do not underline. - underline_flag = 0; + underline_flag_option = 0; break; case 'o': // Do not overstrike (other than emboldening and underlining). @@ -755,15 +855,15 @@ int main(int argc, char **argv) break; case 'r': // Use reverse mode instead of underlining. - reverse_flag = 1; + reverse_flag_option = 1; break; case 'B': // Do bold-underlining as bold. - bold_underline_mode = BOLD_MODE; + bold_underline_mode_option = BOLD_MODE; break; case 'U': // Do bold-underlining as underlining. - bold_underline_mode = UNDERLINE_MODE; + bold_underline_mode_option = UNDERLINE_MODE; break; case 'h': // Use horizontal tabs. @@ -790,15 +890,7 @@ int main(int argc, char **argv) default: assert(0); } - if (old_drawing_scheme) { - italic_flag = 0; - reverse_flag = 0; - } - else { - bold_underline_mode = BOLD_MODE|UNDERLINE_MODE; - bold_flag = 1; - underline_flag = 1; - } + update_options(); if (optind >= argc) do_file("-"); else { |