aboutsummaryrefslogtreecommitdiff
path: root/contrib/groff/src/devices/grotty/tty.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/groff/src/devices/grotty/tty.cpp')
-rw-r--r--contrib/groff/src/devices/grotty/tty.cpp242
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 {