groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] [grotty]: Use terminfo.


From: Lennart Jablonka
Subject: [PATCH v2] [grotty]: Use terminfo.
Date: Mon, 21 Aug 2023 21:40:18 +0000

This has nothing at all to do with making it easier to customize the
look of man pages.

Hyperlinks are still marked up using OSC 8, hoping that whatever
terminal sits in front of the user interprets or ignores those.
Terminfo naturally doesn’t have a capability for hyperlinks.

Autoconf is not informed about the dependence on Curses; we simply link
with -lcurses, as that is what X/Open Curses specifies.

The suggested option to less is changed to -r, which enables passing
through single control characters, because some terminal descriptions
use those; I noticed that tmux’s sgr0 contains ^O.

I’m too lazy to find another name for lines_.
---
v1 → v2:

  - hardcoded escape sequences are eliminated, except for OSC 8
  - variables are renamed appropriately
  - update_attributes is split in two; the new update_attributes’s
    parameter list is not gigantic, I hope
  - errors to do with setupterm and the capabilities are handled
    properly

and more as seen in the interdiff against v1:

  diff --git a/INSTALL.extra b/INSTALL.extra
  index 3527b1929..5ef903c77 100644
  --- a/INSTALL.extra
  +++ b/INSTALL.extra
  @@ -122,7 +122,7 @@ Several programs distributed with GNU roff are written in 
the Perl
   language.  Version 5.6.1 (1 April 2001) or later is required.
   
   The 'uchardet' library is an optional dependency of the 'preconv'
  -program: If this library is found by 'configure', it will be
  +program: if this library is found by 'configure', it will be
   automatically used by 'preconv'.  Discovery of the 'uchardet' library
   requires the 'pkg-config' program to be installed on your system, as
   well as the library's C header files--on a package-based host system,
  diff --git a/NEWS b/NEWS
  index 98be590dd..87990f487 100644
  --- a/NEWS
  +++ b/NEWS
  @@ -94,7 +94,8 @@ grotty
   ------
   
   o The terminfo library is now used for applying text attributes (like
  -  italic, bold, and colors).
  +  italic, bold, and colors).  You now need Curses to run grotty.  The
  +  legacy overstriking output format remains.
   
   Miscellaneous
   -------------
  diff --git a/src/devices/grotty/grotty.1.man b/src/devices/grotty/grotty.1.man
  index 43d9d7ffd..6fbd70612 100644
  --- a/src/devices/grotty/grotty.1.man
  +++ b/src/devices/grotty/grotty.1.man
  @@ -56,8 +56,6 @@ output driver for typewriter-like (terminal) devices
   .RB [ \-i \||\| \-r ]
   .RB [ \-F\~\c
   .IR font-directory ]
  -.RB [ \-T\~\c
  -.IR term ]
   .RI [ file\~ .\|.\|.]
   .YS
   .
  @@ -66,8 +64,6 @@ output driver for typewriter-like (terminal) devices
   .RB [ \-bBdfhouU ]
   .RB [ \-F\~\c
   .IR font-directory ]
  -.RB [ \-T\~\c
  -.IR term ]
   .RI [ file\~ .\|.\|.]
   .YS
   .
  @@ -140,8 +136,8 @@ Output is written to the standard output stream.
   By default,
   .I grotty
   uses
  -.MR terminfo 5
  -to change text attributes
  +.MR terminfo 3
  +capabilities to change text attributes
   (bold,
   italic,
   underline,
  @@ -150,15 +146,6 @@ reverse video
   [\[lq]negative image\[rq]]
   and colors).
   .
  -If no
  -.I TERM
  -environment variable is set
  -or terminfo encounters a different error,
  -.I grotty
  -emits hardcoded SGR escape sequences
  -(from ISO\~6429,
  -popularly called \[lq]ANSI escapes\[rq]).
  -.
   Devices supporting the appropriate sequences can view
   .I roff
   documents using eight different background and foreground colors.
  @@ -180,6 +167,11 @@ which is dependent on the settings of the terminal.
   .
   OSC\~8 hyperlinks are produced for these devices.
   .
  +If the terminal description provides no way of changing the text
  +attributes but does declare that overstriking characters is possible,
  +.I grotty
  +will use the legacy output format.
  +.
   .
   .P
   In keeping with long-standing practice and the rarity of terminals
  @@ -192,7 +184,7 @@ option below.
   .
   .
   .\" ====================================================================
  -.SS "SGR and OSC support in pagers"
  +.SS "Control character support in pagers"
   .\" ====================================================================
   .
   When paging
  @@ -202,6 +194,8 @@ output with
   the latter program must be instructed to pass control characters
   through to the device;
   its
  +.\" TODO: using less -r means putting untrusted input on the terminal;
  +.\" ponder this
   .B \-r
   option is one way to achieve this
   .RI ( less
  @@ -232,7 +226,7 @@ and
   .I nroff
   were first developed but which are no longer in wide use.
   .
  -SGR escape sequences are not emitted;
  +Terminfo capability strings are not emitted;
   bold,
   italic,
   and underlining character attributes are thus not manipulated.
  @@ -440,7 +434,7 @@ Use
   legacy output format
   (see subsection \[lq]Legacy output format\[rq] above).
   .
  -SGR and OSC escape sequences are not emitted.
  +Terminfo capability strings and OSC escape sequences are not emitted.
   .
   .
   .TP
  @@ -499,7 +493,8 @@ or
   .B \-h
   Use literal horizontal tab characters in the output.
   .
  -Tabs are assumed to be set every 8 columns.
  +Unless the terminal description says otherwise,
  +tabs are assumed to be set every 8 columns.
   .
   .
   .TP
  @@ -508,7 +503,7 @@ Render oblique-styled fonts
   .RB ( I
   and
   .BR BI )
  -with the SGR attribute for italic text
  +with the terminfo capability for italic text
   rather than underlined text.
   .
   Many terminals don't support this attribute;
  @@ -521,6 +516,8 @@ Ignored if
   .B \-c
   is also specified.
   .
  +Disables the overstriking fallback for hardcopy terminals.
  +.
   .
   .TP
   .B \-o
  @@ -535,7 +532,7 @@ Render oblique-styled fonts
   .RB ( I
   and
   .BR BI )
  -with the SGR attribute for reverse video text
  +with the terminfo capability for reverse video text
   rather than underlined text.
   .
   Ignored if
  @@ -546,21 +543,6 @@ is also specified.
   .
   .
   .TP
  -.BI \-T\~ term
  -Read description for terminal type
  -.I term
  -and fail if
  -.I terminfo
  -encounters and error.
  -By default,
  -.I grotty
  -takes the terminal type from the environment variable
  -.I TERM
  -and falls back to SGR escape sequences
  -if that is not specified or there is an error.
  -.
  -.
  -.TP
   .B \-u
   Suppress the use of underlining for italic characters in legacy output
   format.
  @@ -598,8 +580,9 @@ see subsection \[lq]Legacy output format\[rq] above.
   .
   .TP
   .I TERM
  -The terminal type for
  -.I terminfo.
  +The terminal type interpreted by the
  +.MR terminfo 3
  +library.
   .
   .
   .br
  diff --git a/src/devices/grotty/tty.cpp b/src/devices/grotty/tty.cpp
  index 9df35d8cd..bbca37ee3 100644
  --- a/src/devices/grotty/tty.cpp
  +++ b/src/devices/grotty/tty.cpp
  @@ -21,6 +21,7 @@ along with this program.  If not, see 
<http://www.gnu.org/licenses/>. */
   #include "device.h"
   #include "ptable.h"
   
  +#include <curses.h>
   #include <term.h>
   
   typedef signed char schar;
  @@ -49,15 +50,12 @@ static bool want_emboldening_by_overstriking = true;
   static bool do_bold;
   static bool want_italics_by_underlining = true;
   static bool do_underline;
  -static bool want_glyph_composition_by_overstriking = true;
  +static bool accept_glyph_composition_by_overstriking = true;
  +static bool do_glyph_composition_by_overstriking;
   static bool allow_drawing_commands = true;
  -static bool want_sgr_italics = false;
  -static bool do_sgr_italics;
  +static bool want_real_italics = false;
   static bool want_reverse_video_for_italics = false;
  -static bool do_reverse_video;
   static bool use_overstriking_drawing_scheme = false;
  -static bool use_terminfo;
  -static char *terminal_name;
   
   static void update_options();
   static void usage(FILE *stream);
  @@ -85,26 +83,14 @@ static unsigned char bold_underline_mode_option = 
BOLD_MODE|UNDERLINE_MODE;
   static unsigned char bold_underline_mode;
   
   #ifndef IS_EBCDIC_HOST
  -#define CSI "\033["
   #define OSC8 "\033]8"
   #define ST "\033\\"
   #else
  -#define CSI "\047["
   #define OSC8 "\047]8"
   #define ST "\047\\"
   #endif
   
  -// SGR handling (ISO 6429)
  -// bold and reverse can be unset separately using ISO 6429, but not
  -// with terminfo
  -static const char *sgr_bold = CSI "1m";
  -static const char *sgr_italic = CSI "3m";
  -static const char *sgr_underline = CSI "4m";
  -static const char *sgr_reverse = CSI "7m";
  -// many terminals can't handle 'CSI 39 m' and 'CSI 49 m' to reset
  -// the foreground and background color, respectively; we thus use
  -// 'CSI 0 m' exclusively
  -static const char *sgr_exit_attributes = CSI "0m";
  +static char *enter_italics_or_the_like_mode;
   
   #define DEFAULT_COLOR_IDX -1
   
  @@ -186,7 +172,8 @@ class tty_printer : public printer {
     bool is_boldfacing;
     bool is_continuously_underlining;
     PTABLE(schar) tty_colors;
  -  void update_attributes(bool, bool, schar, schar, output_character, int);
  +  void overstrike(bool, bool, output_character, int);
  +  void update_attributes(bool, bool, schar, schar);
     schar color_to_idx(color *);
     void add_char(output_character, int, int, int, color *, color *,
                unsigned char);
  @@ -204,6 +191,7 @@ public:
     void set_char(glyph *, font *, const environment *, int, const char *);
     void draw(int, int *, int, const environment *);
     void special(char *, const environment *, char);
  +  void change_color(const environment * const);
     void change_fill_color(const environment * const);
     void put_char(output_character);
     void begin_page(int) { }
  @@ -283,80 +271,68 @@ tty_printer::~tty_printer()
     delete[] lines_;
   }
   
  -/* Update the current text attributes, doing little more than necessary
  -work.  The c and w parameters are not used unless
  -use_overstriking_drawing_scheme and at least one of underline and bold
  -is set. */
  -void tty_printer::update_attributes(bool underline, bool bold,
  -                                 schar fore_idx, schar back_idx,
  -                                 output_character c, int w)
  +// Both ovrestrike and update_attributes need be called for text
  +// attributes; only one of them will take effect.  Call overstrike for
  +// every glyph.  The update_attributes function, too, can be called for
  +// every glyph, as it's a noop for the same attributes.
  +
  +void tty_printer::overstrike(bool underline, bool bold,
  +                          output_character c, int w)
   {
  -  if (use_overstriking_drawing_scheme) {
  -    if (underline) {
  -      if (!w)
  -     warning("can't underline zero-width character");
  -      else {
  -     putchar('_');
  -     putchar('\b');
  -      }
  -    }
  -    if (bold) {
  -      if (!w)
  -     warning("can't print zero-width character in bold");
  -      else {
  -     put_char(c);
  -     putchar('\b');
  -      }
  +  if (!use_overstriking_drawing_scheme)
  +    return;
  +
  +  if (underline) {
  +    if (!w)
  +      warning("can't underline zero-width character");
  +    else {
  +      putchar('_');
  +      putchar('\b');
       }
     }
  -  else {
  -    if (is_underlining && !underline
  -     || is_boldfacing && !bold
  -     || curr_fore_idx != DEFAULT_COLOR_IDX && fore_idx == DEFAULT_COLOR_IDX
  -     || curr_back_idx != DEFAULT_COLOR_IDX && back_idx == DEFAULT_COLOR_IDX) 
{
  -      putp(sgr_exit_attributes);
  -      is_underlining = is_boldfacing = false;
  -      curr_fore_idx = curr_back_idx = DEFAULT_COLOR_IDX;
  +  if (bold) {
  +    if (!w)
  +      warning("can't print zero-width character in bold");
  +    else {
  +      put_char(c);
  +      putchar('\b');
       }
  +  }
  +}
   
  -    if (!is_underlining && underline) {
  -      if (do_sgr_italics)
  -     putp(sgr_italic);
  -      else if (do_reverse_video)
  -     putp(sgr_reverse);
  -      else
  -     putp(sgr_underline);
  -      is_underlining = true;
  -    }
  +void tty_printer::update_attributes(bool underline, bool bold,
  +                                 schar fore_idx, schar back_idx)
  +{
  +  if (use_overstriking_drawing_scheme)
  +    return;
   
  -    if (!is_boldfacing && bold) {
  -      putp(sgr_bold);
  -      is_boldfacing = true;
  -    }
  +  if (is_underlining && !underline
  +      || is_boldfacing && !bold
  +      || curr_fore_idx != DEFAULT_COLOR_IDX && fore_idx == DEFAULT_COLOR_IDX
  +      || curr_back_idx != DEFAULT_COLOR_IDX && back_idx == 
DEFAULT_COLOR_IDX) {
  +    putp(exit_attribute_mode);
  +    is_underlining = is_boldfacing = false;
  +    curr_fore_idx = curr_back_idx = DEFAULT_COLOR_IDX;
  +  }
   
  -    if (curr_fore_idx != fore_idx) {
  -      if (use_terminfo)
  -     putp(tparm(set_a_foreground, fore_idx, 0, 0, 0, 0, 0, 0, 0, 0));
  -      else {
  -     fputs(CSI, stdout);
  -     putchar('3');
  -     putchar(fore_idx + '0');
  -     putchar('m');
  -      }
  -      curr_fore_idx = fore_idx;
  -    }
  +  if (!is_underlining && underline) {
  +    putp(enter_italics_or_the_like_mode);
  +    is_underlining = true;
  +  }
   
  -    if (curr_back_idx != back_idx) {
  -      if (use_terminfo)
  -     putp(tparm(set_a_background, back_idx, 0, 0, 0, 0, 0, 0, 0, 0));
  -      else {
  -     fputs(CSI, stdout);
  -     putchar('4');
  -     putchar(back_idx + '0');
  -     putchar('m');
  -      }
  -      curr_back_idx = back_idx;
  -    }
  +  if (!is_boldfacing && bold) {
  +    putp(enter_bold_mode);
  +    is_boldfacing = true;
  +  }
  +
  +  if (curr_fore_idx != fore_idx) {
  +    putp(tparm(set_a_foreground, fore_idx, 0, 0, 0, 0, 0, 0, 0, 0));
  +    curr_fore_idx = fore_idx;
  +  }
  +
  +  if (curr_back_idx != back_idx) {
  +    putp(tparm(set_a_background, back_idx, 0, 0, 0, 0, 0, 0, 0, 0));
  +    curr_back_idx = back_idx;
     }
   }
   
  @@ -496,8 +472,6 @@ void tty_printer::special(char *arg, const environment 
*env, char type)
   // repeated arbitrarily and are separated by colons.  Omission of the
   // URI ends the hyperlink that was begun by specifying it.  See
   // <https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda>.
  -//
  -// TODO(humm): What should be done with OSC 8 when using terminfo?
   void tty_printer::special_link(const char *arg, const environment *env)
   {
     static bool is_link_active = false;
  @@ -562,6 +536,11 @@ void tty_printer::special_link(const char *arg, const 
environment *env)
       simple_add_char(*s, env);
   }
   
  +void tty_printer::change_color(const environment * const env)
  +{
  +  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, 0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
  @@ -798,7 +777,7 @@ void tty_printer::end_page(int page_length)
          nextp->code = p->code;
          continue;
        }
  -     if (!want_glyph_composition_by_overstriking)
  +     if (!do_glyph_composition_by_overstriking)
          continue;
         }
         if (hpos > p->hpos) {
  @@ -807,7 +786,9 @@ void tty_printer::end_page(int page_length)
          hpos--;
        } while (hpos > p->hpos);
         }
  -      else {
  +      else if (p->hpos > hpos) {
  +     update_attributes(is_continuously_underlining, is_boldfacing,
  +                       curr_fore_idx, curr_back_idx);
        if (want_horizontal_tabs) {
          for (;;) {
            int next_tab_pos = ((hpos + tab_width) / tab_width) * tab_width;
  @@ -816,36 +797,32 @@ void tty_printer::end_page(int page_length)
            // TODO(humm): Should we not take the width of the actual
            // tab?  The current status works, albeit not with
            // typewriters: _\b\t is rendered as multiple underlined
  -         // cells by less.  We could pass update_attributes the width
  +         // cells by less.  We could pass overstrike the width
            // the actual tab will have and let it emit multiple
            // underlines.
  -         update_attributes(is_continuously_underlining, is_boldfacing,
  -                           curr_fore_idx, curr_back_idx, '\t', p->w);
  +         overstrike(is_continuously_underlining, false, '\t', p->w);
            putchar('\t');
            hpos = next_tab_pos;
          }
        }
        for (; hpos < p->hpos; hpos++) {
  -       update_attributes(is_continuously_underlining, is_boldfacing,
  -                         curr_fore_idx, curr_back_idx, ' ', p->w);
  +       overstrike(is_continuously_underlining, false, ' ', p->w);
          putchar(' ');
        }
         }
         assert(hpos == p->hpos);
         if (p->mode & COLOR_CHANGE) {
  -     // test because we don't have any (c,w) to pass and won't do
  -     // colors if those would be used
  -     if (!use_overstriking_drawing_scheme)
  -       update_attributes(is_underlining, is_boldfacing,
  -                         p->fore_color_idx, p->back_color_idx, 0, 0);
  +     update_attributes(is_underlining, is_boldfacing,
  +                       p->fore_color_idx, p->back_color_idx);
        continue;
         }
  +      overstrike(p->mode & UNDERLINE_MODE, p->mode & BOLD_MODE, p->code, 
p->w);
         update_attributes(p->mode & UNDERLINE_MODE, p->mode & BOLD_MODE,
  -                     p->fore_color_idx, p->back_color_idx, p->code, p->w);
  +                     p->fore_color_idx, p->back_color_idx);
         put_char(p->code);
         hpos += p->w / font::hor;
       }
  -    update_attributes(false, false, DEFAULT_COLOR_IDX, DEFAULT_COLOR_IDX, 0, 
0);
  +    update_attributes(false, false, DEFAULT_COLOR_IDX, DEFAULT_COLOR_IDX);
       putchar('\n');
     }
     if (want_form_feeds) {
  @@ -871,34 +848,82 @@ printer *make_printer()
   static void update_options()
   {
     if (use_overstriking_drawing_scheme) {
  -    do_sgr_italics = false;
  -    do_reverse_video = false;
       bold_underline_mode = bold_underline_mode_option;
       do_bold = want_emboldening_by_overstriking;
       do_underline = want_italics_by_underlining;
  +    do_glyph_composition_by_overstriking =
  +      accept_glyph_composition_by_overstriking;
  +    return;
     }
  -  else {
  -    // TODO(humm): Do better error handling.
  -    int err;
  -    setupterm(terminal_name, 1, terminal_name != NULL ? NULL : &err);
  -    if (err == 1) {
  -      // TODO(humm): Do error handling for the capabilities.  Can they
  -      // be null pointers?  Can they be (char*)-1?  Should we fall back
  -      // to underline if italic is not available and the like?  Should
  -      // we ignore attributes we can't fulfill, or should we abort?
  -      use_terminfo = true;
  -      sgr_bold = enter_bold_mode;
  -      sgr_italic = enter_italics_mode;
  -      sgr_underline = enter_underline_mode;
  -      sgr_reverse = enter_reverse_mode;
  -      sgr_exit_attributes = exit_attribute_mode;
  -      tab_width = init_tabs;
  +
  +  bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
  +  do_bold = true;
  +  do_underline = true;
  +
  +  int err;
  +  if (setupterm(NULL, 1, &err) == ERR)
  +    switch (err) {
  +      // It's a little sad that we can't use Curses's own error
  +      // strings, just to be able to handle hardcopy terminals,
  +      // only because ncurses behaves in a non-standard manner when
  +      // stumbling upon the hc capability.
  +    case -1:
  +      fatal("terminfo database not found");
  +    case 0:
  +      fatal("terminal description not found");
  +    case 1: // hardcopy terminal (non standard) / success (standard)
  +      // We check for over_strike anyway.  Ncurses is nice enough
  +      // to load the capabilities anyway.
  +      ;
       }
  -    do_sgr_italics = want_sgr_italics;
  -    do_reverse_video = want_reverse_video_for_italics;
  -    bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
  -    do_bold = true;
  -    do_underline = true;
  +
  +  if (want_real_italics)
  +    enter_italics_or_the_like_mode = enter_italics_mode;
  +  else if (want_reverse_video_for_italics)
  +    enter_italics_or_the_like_mode = enter_reverse_mode;
  +  else
  +    enter_italics_or_the_like_mode = enter_underline_mode;
  +
  +  if (tab_width == -2)
  +    fatal("bad it (init_tabs) capability");
  +
  +  tab_width = init_tabs != -1 ? init_tabs : 8;
  +
  +  if (over_strike == -1)
  +    fatal("bad os (over_strike) capability");
  +
  +  do_glyph_composition_by_overstriking =
  +    accept_glyph_composition_by_overstriking && over_strike;
  +
  +  static const struct {
  +    char *cap;
  +    char const *nullmsg;
  +    char const *negonemsg;
  +  } string_caps[] = {
  +    // all the string capabilities we use in the program
  +    {enter_bold_mode, "can't make text bold", "bad bold capability"},
  +    {enter_italics_or_the_like_mode, "can't make text italic (or the like)",
  +      "bad italics (or the like) capability"},
  +    {exit_attribute_mode, "can't disable text attributes",
  +      "bad sgr0 (exit attributes) capability"},
  +    {set_a_foreground, "can't colorize text",
  +      "bad setaf (foreground color) capability"},
  +    {set_a_background, "can't colorize text",
  +      "bad setab (background color) capability"},
  +  };
  +
  +  for (int i = 0; i < sizeof string_caps / sizeof *string_caps; ++i) {
  +    if (string_caps[i].cap == NULL) {
  +      if (over_strike && !want_real_italics && 
!want_reverse_video_for_italics) {
  +     use_overstriking_drawing_scheme = true;
  +     update_options();
  +     return;
  +      }
  +      else
  +     fatal(string_caps[i].nullmsg);
  +    }
  +    else if (string_caps[i].cap == (char *)-1)
  +      fatal(string_caps[i].negonemsg);
     }
   }
   
  @@ -916,7 +941,7 @@ int main(int argc, char **argv)
       { "version", no_argument, 0, 'v' },
       { NULL, 0, 0, 0 }
     };
  -  while ((c = getopt_long(argc, argv, "bBcdfF:hiI:orT:uUv", long_options, 
NULL))
  +  while ((c = getopt_long(argc, argv, "bBcdfF:hiI:oruUv", long_options, 
NULL))
         != EOF)
       switch(c) {
       case 'v':
  @@ -925,7 +950,7 @@ int main(int argc, char **argv)
         break;
       case 'i':
         // Use italic font instead of underlining.
  -      want_sgr_italics = true;
  +      want_real_italics = true;
         break;
       case 'I':
         // ignore include search path
  @@ -944,7 +969,7 @@ int main(int argc, char **argv)
         break;
       case 'o':
         // Do not overstrike (other than emboldening and underlining).
  -      want_glyph_composition_by_overstriking = false;
  +      accept_glyph_composition_by_overstriking = false;
         break;
       case 'r':
         // Use reverse mode instead of underlining.
  @@ -972,9 +997,6 @@ int main(int argc, char **argv)
         // Ignore \D commands.
         allow_drawing_commands = false;
         break;
  -    case 'T':
  -      terminal_name = optarg;
  -      break;
       case CHAR_MAX + 1: // --help
         usage(stdout);
         break;
  @@ -998,7 +1020,7 @@ int main(int argc, char **argv)
   static void usage(FILE *stream)
   {
     fprintf(stream,
  -"usage: %s [-bBcdfhioruU] [-F font-directory] [-T term] [file ...]\n"
  +"usage: %s [-bBcdfhioruU] [-F font-directory] [file ...]\n"
   "usage: %s {-v | --version}\n"
   "usage: %s --help\n",
          program_name, program_name, program_name);

 INSTALL.extra                   |   3 +
 NEWS                            |  10 +
 src/devices/grotty/grotty.1.man |  40 ++--
 src/devices/grotty/grotty.am    |   3 +-
 src/devices/grotty/tty.cpp      | 333 ++++++++++++++++----------------
 5 files changed, 209 insertions(+), 180 deletions(-)

diff --git a/INSTALL.extra b/INSTALL.extra
index 78d4139af..5ef903c77 100644
--- a/INSTALL.extra
+++ b/INSTALL.extra
@@ -128,6 +128,9 @@ requires the 'pkg-config' program to be installed on your 
system, as
 well as the library's C header files--on a package-based host system,
 this can mean installing uchardet's '-dev' or '-devel' package.
 
+The 'grotty' program depends on a Curses library, which is specified
+by X/Open Curses.
+
 URW fonts
 ---------
 
diff --git a/NEWS b/NEWS
index 81de79c1b..87990f487 100644
--- a/NEWS
+++ b/NEWS
@@ -87,6 +87,16 @@ o The s (ms) macro package now sets the vertical spacing 
register
   size of 20 points, the vertical spacing now defaults to 24 points
   rather than 22.
 
+Output drivers
+--------------
+
+grotty
+------
+
+o The terminfo library is now used for applying text attributes (like
+  italic, bold, and colors).  You now need Curses to run grotty.  The
+  legacy overstriking output format remains.
+
 Miscellaneous
 -------------
 
diff --git a/src/devices/grotty/grotty.1.man b/src/devices/grotty/grotty.1.man
index 24cea9801..6fbd70612 100644
--- a/src/devices/grotty/grotty.1.man
+++ b/src/devices/grotty/grotty.1.man
@@ -135,10 +135,9 @@ Output is written to the standard output stream.
 .P
 By default,
 .I grotty
-emits SGR escape sequences
-(from ISO\~6429,
-popularly called \[lq]ANSI escapes\[rq])
-to change text attributes
+uses
+.MR terminfo 3
+capabilities to change text attributes
 (bold,
 italic,
 underline,
@@ -168,6 +167,11 @@ which is dependent on the settings of the terminal.
 .
 OSC\~8 hyperlinks are produced for these devices.
 .
+If the terminal description provides no way of changing the text
+attributes but does declare that overstriking characters is possible,
+.I grotty
+will use the legacy output format.
+.
 .
 .P
 In keeping with long-standing practice and the rarity of terminals
@@ -180,17 +184,19 @@ option below.
 .
 .
 .\" ====================================================================
-.SS "SGR and OSC support in pagers"
+.SS "Control character support in pagers"
 .\" ====================================================================
 .
 When paging
 .IR grotty 's
 output with
 .MR less 1 ,
-the latter program must be instructed to pass SGR and OSC sequences
+the latter program must be instructed to pass control characters
 through to the device;
 its
-.B \-R
+.\" TODO: using less -r means putting untrusted input on the terminal;
+.\" ponder this
+.B \-r
 option is one way to achieve this
 .RI ( less
 version 566 or later is required for OSC\~8 support).
@@ -220,7 +226,7 @@ and
 .I nroff
 were first developed but which are no longer in wide use.
 .
-SGR escape sequences are not emitted;
+Terminfo capability strings are not emitted;
 bold,
 italic,
 and underlining character attributes are thus not manipulated.
@@ -428,7 +434,7 @@ Use
 legacy output format
 (see subsection \[lq]Legacy output format\[rq] above).
 .
-SGR and OSC escape sequences are not emitted.
+Terminfo capability strings and OSC escape sequences are not emitted.
 .
 .
 .TP
@@ -487,7 +493,8 @@ or
 .B \-h
 Use literal horizontal tab characters in the output.
 .
-Tabs are assumed to be set every 8 columns.
+Unless the terminal description says otherwise,
+tabs are assumed to be set every 8 columns.
 .
 .
 .TP
@@ -496,7 +503,7 @@ Render oblique-styled fonts
 .RB ( I
 and
 .BR BI )
-with the SGR attribute for italic text
+with the terminfo capability for italic text
 rather than underlined text.
 .
 Many terminals don't support this attribute;
@@ -509,6 +516,8 @@ Ignored if
 .B \-c
 is also specified.
 .
+Disables the overstriking fallback for hardcopy terminals.
+.
 .
 .TP
 .B \-o
@@ -523,7 +532,7 @@ Render oblique-styled fonts
 .RB ( I
 and
 .BR BI )
-with the SGR attribute for reverse video text
+with the terminfo capability for reverse video text
 rather than underlined text.
 .
 Ignored if
@@ -569,6 +578,13 @@ option were specified;
 see subsection \[lq]Legacy output format\[rq] above.
 .
 .
+.TP
+.I TERM
+The terminal type interpreted by the
+.MR terminfo 3
+library.
+.
+.
 .br
 .ne 3v \" Keep section heading and paragraph tag together.
 .\" ====================================================================
diff --git a/src/devices/grotty/grotty.am b/src/devices/grotty/grotty.am
index 14921c562..a9d2fe1c1 100644
--- a/src/devices/grotty/grotty.am
+++ b/src/devices/grotty/grotty.am
@@ -20,7 +20,8 @@ grotty_SOURCES = src/devices/grotty/tty.cpp
 grotty_LDADD = $(LIBM) \
   libdriver.a \
   libgroff.a \
-  lib/libgnu.a
+  lib/libgnu.a \
+  -lcurses
 man1_MANS += src/devices/grotty/grotty.1
 EXTRA_DIST += \
   src/devices/grotty/grotty.1.man \
diff --git a/src/devices/grotty/tty.cpp b/src/devices/grotty/tty.cpp
index 1b92ad8c0..bbca37ee3 100644
--- a/src/devices/grotty/tty.cpp
+++ b/src/devices/grotty/tty.cpp
@@ -21,6 +21,9 @@ along with this program.  If not, see 
<http://www.gnu.org/licenses/>. */
 #include "device.h"
 #include "ptable.h"
 
+#include <curses.h>
+#include <term.h>
+
 typedef signed char schar;
 
 declare_ptable(schar)
@@ -28,8 +31,6 @@ implement_ptable(schar)
 
 extern "C" const char *Version_string;
 
-#define putstring(s) fputs(s, stdout)
-
 #ifndef SHRT_MIN
 #define SHRT_MIN (-32768)
 #endif
@@ -38,7 +39,7 @@ extern "C" const char *Version_string;
 #define SHRT_MAX 32767
 #endif
 
-#define TAB_WIDTH 8
+static int tab_width = 8;
 
 // A character of the output device fits in a 32-bit word.
 typedef unsigned int output_character;
@@ -49,17 +50,20 @@ static bool want_emboldening_by_overstriking = true;
 static bool do_bold;
 static bool want_italics_by_underlining = true;
 static bool do_underline;
-static bool want_glyph_composition_by_overstriking = true;
+static bool accept_glyph_composition_by_overstriking = true;
+static bool do_glyph_composition_by_overstriking;
 static bool allow_drawing_commands = true;
-static bool want_sgr_italics = false;
-static bool do_sgr_italics;
+static bool want_real_italics = false;
 static bool want_reverse_video_for_italics = false;
-static bool do_reverse_video;
 static bool use_overstriking_drawing_scheme = false;
 
 static void update_options();
 static void usage(FILE *stream);
 
+// TODO(humm): We can get proper line drawing characters from terminfo
+// using acsc, smacs, rmacs; we could do that for -Tascii + terminfo.
+// There are other characters there we could theoreticlly use as well,
+// like degree and pi.
 static int hline_char = '-';
 static int vline_char = '|';
 
@@ -79,28 +83,14 @@ static unsigned char bold_underline_mode_option = 
BOLD_MODE|UNDERLINE_MODE;
 static unsigned char bold_underline_mode;
 
 #ifndef IS_EBCDIC_HOST
-#define CSI "\033["
 #define OSC8 "\033]8"
 #define ST "\033\\"
 #else
-#define CSI "\047["
 #define OSC8 "\047]8"
 #define ST "\047\\"
 #endif
 
-// SGR handling (ISO 6429)
-#define SGR_BOLD CSI "1m"
-#define SGR_NO_BOLD CSI "22m"
-#define SGR_ITALIC CSI "3m"
-#define SGR_NO_ITALIC CSI "23m"
-#define SGR_UNDERLINE CSI "4m"
-#define SGR_NO_UNDERLINE CSI "24m"
-#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 background color, respectively; we thus use
-// 'CSI 0 m' exclusively
-#define SGR_DEFAULT CSI "0m"
+static char *enter_italics_or_the_like_mode;
 
 #define DEFAULT_COLOR_IDX -1
 
@@ -172,7 +162,7 @@ public:
 
 
 class tty_printer : public printer {
-  tty_glyph **lines;
+  tty_glyph **lines_; // clashes with Curses lines
   int nlines;
   int cached_v;
   int cached_vpos;
@@ -182,8 +172,8 @@ class tty_printer : public printer {
   bool is_boldfacing;
   bool is_continuously_underlining;
   PTABLE(schar) tty_colors;
-  void make_underline(int);
-  void make_bold(output_character, int);
+  void overstrike(bool, bool, output_character, int);
+  void update_attributes(bool, bool, schar, schar);
   schar color_to_idx(color *);
   void add_char(output_character, int, int, int, color *, color *,
                unsigned char);
@@ -204,7 +194,6 @@ public:
   void change_color(const environment * const);
   void change_fill_color(const environment * const);
   void put_char(output_character);
-  void put_color(schar, int);
   void begin_page(int) { }
   void end_page(int);
   font *make_font(const char *);
@@ -271,20 +260,29 @@ tty_printer::tty_printer() : cached_v(0)
   (void)tty_color(color::MAX_COLOR_VAL, 0, color::MAX_COLOR_VAL, &dummy, 5);
   (void)tty_color(0, color::MAX_COLOR_VAL, color::MAX_COLOR_VAL, &dummy, 6);
   nlines = 66;
-  lines = new tty_glyph *[nlines];
+  lines_ = new tty_glyph *[nlines];
   for (int i = 0; i < nlines; i++)
-    lines[i] = 0;
+    lines_[i] = 0;
   is_continuously_underlining = false;
 }
 
 tty_printer::~tty_printer()
 {
-  delete[] lines;
+  delete[] lines_;
 }
 
-void tty_printer::make_underline(int w)
+// Both ovrestrike and update_attributes need be called for text
+// attributes; only one of them will take effect.  Call overstrike for
+// every glyph.  The update_attributes function, too, can be called for
+// every glyph, as it's a noop for the same attributes.
+
+void tty_printer::overstrike(bool underline, bool bold,
+                            output_character c, int w)
 {
-  if (use_overstriking_drawing_scheme) {
+  if (!use_overstriking_drawing_scheme)
+    return;
+
+  if (underline) {
     if (!w)
       warning("can't underline zero-width character");
     else {
@@ -292,22 +290,7 @@ void tty_printer::make_underline(int w)
       putchar('\b');
     }
   }
-  else {
-    if (!is_underlining) {
-      if (do_sgr_italics)
-       putstring(SGR_ITALIC);
-      else if (do_reverse_video)
-       putstring(SGR_REVERSE);
-      else
-       putstring(SGR_UNDERLINE);
-    }
-    is_underlining = true;
-  }
-}
-
-void tty_printer::make_bold(output_character c, int w)
-{
-  if (use_overstriking_drawing_scheme) {
+  if (bold) {
     if (!w)
       warning("can't print zero-width character in bold");
     else {
@@ -315,11 +298,42 @@ void tty_printer::make_bold(output_character c, int w)
       putchar('\b');
     }
   }
-  else {
-    if (!is_boldfacing)
-      putstring(SGR_BOLD);
+}
+
+void tty_printer::update_attributes(bool underline, bool bold,
+                                   schar fore_idx, schar back_idx)
+{
+  if (use_overstriking_drawing_scheme)
+    return;
+
+  if (is_underlining && !underline
+      || is_boldfacing && !bold
+      || curr_fore_idx != DEFAULT_COLOR_IDX && fore_idx == DEFAULT_COLOR_IDX
+      || curr_back_idx != DEFAULT_COLOR_IDX && back_idx == DEFAULT_COLOR_IDX) {
+    putp(exit_attribute_mode);
+    is_underlining = is_boldfacing = false;
+    curr_fore_idx = curr_back_idx = DEFAULT_COLOR_IDX;
+  }
+
+  if (!is_underlining && underline) {
+    putp(enter_italics_or_the_like_mode);
+    is_underlining = true;
+  }
+
+  if (!is_boldfacing && bold) {
+    putp(enter_bold_mode);
     is_boldfacing = true;
   }
+
+  if (curr_fore_idx != fore_idx) {
+    putp(tparm(set_a_foreground, fore_idx, 0, 0, 0, 0, 0, 0, 0, 0));
+    curr_fore_idx = fore_idx;
+  }
+
+  if (curr_back_idx != back_idx) {
+    putp(tparm(set_a_background, back_idx, 0, 0, 0, 0, 0, 0, 0, 0));
+    curr_back_idx = back_idx;
+  }
 }
 
 schar tty_printer::color_to_idx(color *col)
@@ -372,11 +386,11 @@ void tty_printer::add_char(output_character c, int w,
            " quantum");
     vpos = v / font::vert;
     if (vpos > nlines) {
-      tty_glyph **old_lines = lines;
-      lines = new tty_glyph *[vpos + 1];
-      memcpy(lines, old_lines, nlines * sizeof(tty_glyph *));
+      tty_glyph **old_lines = lines_;
+      lines_ = new tty_glyph *[vpos + 1];
+      memcpy(lines_, old_lines, nlines * sizeof(tty_glyph *));
       for (int i = nlines; i <= vpos; i++)
-       lines[i] = 0;
+       lines_[i] = 0;
       delete[] old_lines;
       nlines = vpos + 1;
     }
@@ -403,7 +417,7 @@ void tty_printer::add_char(output_character c, int w,
   // at each hpos, and otherwise in order of occurrence.
 
   tty_glyph **pp;
-  for (pp = lines + (vpos - 1); *pp; pp = &(*pp)->next)
+  for (pp = lines_ + (vpos - 1); *pp; pp = &(*pp)->next)
     if ((*pp)->hpos < hpos
        || ((*pp)->hpos == hpos && (*pp)->order() >= g->order()))
       break;
@@ -683,42 +697,12 @@ void tty_printer::put_char(output_character wc)
     do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3f) | 0x80);
       while (count > 0);
     *++p = '\0';
-    putstring(buf);
+    fputs(buf, stdout);
   }
   else
     putchar(wc);
 }
 
-void tty_printer::put_color(schar color_index, int back)
-{
-  if (color_index == DEFAULT_COLOR_IDX) {
-    putstring(SGR_DEFAULT);
-    // set bold and underline again
-    if (is_boldfacing)
-      putstring(SGR_BOLD);
-    if (is_underlining) {
-      if (do_sgr_italics)
-       putstring(SGR_ITALIC);
-      else if (do_reverse_video)
-       putstring(SGR_REVERSE);
-      else
-       putstring(SGR_UNDERLINE);
-    }
-    // set other color again
-    back = !back;
-    color_index = back ? curr_back_idx : curr_fore_idx;
-  }
-  if (color_index != DEFAULT_COLOR_IDX) {
-    putstring(CSI);
-    if (back)
-      putchar('4');
-    else
-      putchar('3');
-    putchar(color_index + '0');
-    putchar('m');
-  }
-}
-
 // The possible Unicode combinations for crossing characters.
 //
 // '  ' = 0, ' -' = 4, '- ' = 8, '--' = 12,
@@ -741,7 +725,7 @@ void tty_printer::end_page(int page_length)
   int lines_per_page = page_length / font::vert;
   int last_line;
   for (last_line = nlines; last_line > 0; last_line--)
-    if (lines[last_line - 1])
+    if (lines_[last_line - 1])
       break;
 #if 0
   if (last_line > lines_per_page) {
@@ -757,8 +741,8 @@ void tty_printer::end_page(int page_length)
   }
 #endif
   for (int i = 0; i < last_line; i++) {
-    tty_glyph *p = lines[i];
-    lines[i] = 0;
+    tty_glyph *p = lines_[i];
+    lines_[i] = 0;
     tty_glyph *g = 0;
     while (p) {
       tty_glyph *tem = p->next;
@@ -793,7 +777,7 @@ void tty_printer::end_page(int page_length)
          nextp->code = p->code;
          continue;
        }
-       if (!want_glyph_composition_by_overstriking)
+       if (!do_glyph_composition_by_overstriking)
          continue;
       }
       if (hpos > p->hpos) {
@@ -802,92 +786,43 @@ void tty_printer::end_page(int page_length)
          hpos--;
        } while (hpos > p->hpos);
       }
-      else {
+      else if (p->hpos > hpos) {
+       update_attributes(is_continuously_underlining, is_boldfacing,
+                         curr_fore_idx, curr_back_idx);
        if (want_horizontal_tabs) {
          for (;;) {
-           int next_tab_pos = ((hpos + TAB_WIDTH) / TAB_WIDTH) * TAB_WIDTH;
+           int next_tab_pos = ((hpos + tab_width) / tab_width) * tab_width;
            if (next_tab_pos > p->hpos)
              break;
-           if (is_continuously_underlining)
-             make_underline(p->w);
-           else if (!use_overstriking_drawing_scheme
-                    && is_underlining) {
-             if (do_sgr_italics)
-               putstring(SGR_NO_ITALIC);
-             else if (do_reverse_video)
-               putstring(SGR_NO_REVERSE);
-             else
-               putstring(SGR_NO_UNDERLINE);
-             is_underlining = false;
-           }
+           // TODO(humm): Should we not take the width of the actual
+           // tab?  The current status works, albeit not with
+           // typewriters: _\b\t is rendered as multiple underlined
+           // cells by less.  We could pass overstrike the width
+           // the actual tab will have and let it emit multiple
+           // underlines.
+           overstrike(is_continuously_underlining, false, '\t', p->w);
            putchar('\t');
            hpos = next_tab_pos;
          }
        }
        for (; hpos < p->hpos; hpos++) {
-         if (is_continuously_underlining)
-           make_underline(p->w);
-         else if (!use_overstriking_drawing_scheme && is_underlining) {
-           if (do_sgr_italics)
-             putstring(SGR_NO_ITALIC);
-           else if (do_reverse_video)
-             putstring(SGR_NO_REVERSE);
-           else
-             putstring(SGR_NO_UNDERLINE);
-           is_underlining = false;
-         }
+         overstrike(is_continuously_underlining, false, ' ', p->w);
          putchar(' ');
        }
       }
       assert(hpos == p->hpos);
       if (p->mode & COLOR_CHANGE) {
-       if (!use_overstriking_drawing_scheme) {
-         if (p->fore_color_idx != curr_fore_idx) {
-           put_color(p->fore_color_idx, 0);
-           curr_fore_idx = p->fore_color_idx;
-         }
-         if (p->back_color_idx != curr_back_idx) {
-           put_color(p->back_color_idx, 1);
-           curr_back_idx = p->back_color_idx;
-         }
-       }
+       update_attributes(is_underlining, is_boldfacing,
+                         p->fore_color_idx, p->back_color_idx);
        continue;
       }
-      if (p->mode & UNDERLINE_MODE)
-       make_underline(p->w);
-      else if (!use_overstriking_drawing_scheme && is_underlining) {
-       if (do_sgr_italics)
-         putstring(SGR_NO_ITALIC);
-       else if (do_reverse_video)
-         putstring(SGR_NO_REVERSE);
-       else
-         putstring(SGR_NO_UNDERLINE);
-       is_underlining = false;
-      }
-      if (p->mode & BOLD_MODE)
-       make_bold(p->code, p->w);
-      else if (!use_overstriking_drawing_scheme && is_boldfacing) {
-       putstring(SGR_NO_BOLD);
-       is_boldfacing = false;
-      }
-      if (!use_overstriking_drawing_scheme) {
-       if (p->fore_color_idx != curr_fore_idx) {
-         put_color(p->fore_color_idx, 0);
-         curr_fore_idx = p->fore_color_idx;
-       }
-       if (p->back_color_idx != curr_back_idx) {
-         put_color(p->back_color_idx, 1);
-         curr_back_idx = p->back_color_idx;
-       }
-      }
+      overstrike(p->mode & UNDERLINE_MODE, p->mode & BOLD_MODE, p->code, p->w);
+      update_attributes(p->mode & UNDERLINE_MODE, p->mode & BOLD_MODE,
+                       p->fore_color_idx, p->back_color_idx);
       put_char(p->code);
       hpos += p->w / font::hor;
     }
-    if (!use_overstriking_drawing_scheme
-       && (is_boldfacing || is_underlining
-           || curr_fore_idx != DEFAULT_COLOR_IDX
-           || curr_back_idx != DEFAULT_COLOR_IDX))
-      putstring(SGR_DEFAULT);
+    update_attributes(false, false, DEFAULT_COLOR_IDX, DEFAULT_COLOR_IDX);
     putchar('\n');
   }
   if (want_form_feeds) {
@@ -913,18 +848,82 @@ printer *make_printer()
 static void update_options()
 {
   if (use_overstriking_drawing_scheme) {
-    do_sgr_italics = false;
-    do_reverse_video = false;
     bold_underline_mode = bold_underline_mode_option;
     do_bold = want_emboldening_by_overstriking;
     do_underline = want_italics_by_underlining;
+    do_glyph_composition_by_overstriking =
+      accept_glyph_composition_by_overstriking;
+    return;
   }
-  else {
-    do_sgr_italics = want_sgr_italics;
-    do_reverse_video = want_reverse_video_for_italics;
-    bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
-    do_bold = true;
-    do_underline = true;
+
+  bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
+  do_bold = true;
+  do_underline = true;
+
+  int err;
+  if (setupterm(NULL, 1, &err) == ERR)
+    switch (err) {
+      // It's a little sad that we can't use Curses's own error
+      // strings, just to be able to handle hardcopy terminals,
+      // only because ncurses behaves in a non-standard manner when
+      // stumbling upon the hc capability.
+    case -1:
+      fatal("terminfo database not found");
+    case 0:
+      fatal("terminal description not found");
+    case 1: // hardcopy terminal (non standard) / success (standard)
+      // We check for over_strike anyway.  Ncurses is nice enough
+      // to load the capabilities anyway.
+      ;
+    }
+
+  if (want_real_italics)
+    enter_italics_or_the_like_mode = enter_italics_mode;
+  else if (want_reverse_video_for_italics)
+    enter_italics_or_the_like_mode = enter_reverse_mode;
+  else
+    enter_italics_or_the_like_mode = enter_underline_mode;
+
+  if (tab_width == -2)
+    fatal("bad it (init_tabs) capability");
+
+  tab_width = init_tabs != -1 ? init_tabs : 8;
+
+  if (over_strike == -1)
+    fatal("bad os (over_strike) capability");
+
+  do_glyph_composition_by_overstriking =
+    accept_glyph_composition_by_overstriking && over_strike;
+
+  static const struct {
+    char *cap;
+    char const *nullmsg;
+    char const *negonemsg;
+  } string_caps[] = {
+    // all the string capabilities we use in the program
+    {enter_bold_mode, "can't make text bold", "bad bold capability"},
+    {enter_italics_or_the_like_mode, "can't make text italic (or the like)",
+      "bad italics (or the like) capability"},
+    {exit_attribute_mode, "can't disable text attributes",
+      "bad sgr0 (exit attributes) capability"},
+    {set_a_foreground, "can't colorize text",
+      "bad setaf (foreground color) capability"},
+    {set_a_background, "can't colorize text",
+      "bad setab (background color) capability"},
+  };
+
+  for (int i = 0; i < sizeof string_caps / sizeof *string_caps; ++i) {
+    if (string_caps[i].cap == NULL) {
+      if (over_strike && !want_real_italics && 
!want_reverse_video_for_italics) {
+       use_overstriking_drawing_scheme = true;
+       update_options();
+       return;
+      }
+      else
+       fatal(string_caps[i].nullmsg);
+    }
+    else if (string_caps[i].cap == (char *)-1)
+      fatal(string_caps[i].negonemsg);
   }
 }
 
@@ -951,7 +950,7 @@ int main(int argc, char **argv)
       break;
     case 'i':
       // Use italic font instead of underlining.
-      want_sgr_italics = true;
+      want_real_italics = true;
       break;
     case 'I':
       // ignore include search path
@@ -970,7 +969,7 @@ int main(int argc, char **argv)
       break;
     case 'o':
       // Do not overstrike (other than emboldening and underlining).
-      want_glyph_composition_by_overstriking = false;
+      accept_glyph_composition_by_overstriking = false;
       break;
     case 'r':
       // Use reverse mode instead of underlining.
-- 
2.41.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]