texlive[51473] trunk: fontools (26jun19)

commits+karl at tug.org commits+karl at tug.org
Wed Jun 26 22:41:25 CEST 2019


Revision: 51473
          http://tug.org/svn/texlive?view=revision&revision=51473
Author:   karl
Date:     2019-06-26 22:41:25 +0200 (Wed, 26 Jun 2019)
Log Message:
-----------
fontools (26jun19)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/fontools/afm2afm
    trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst
    trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx
    trunk/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl
    trunk/Master/texmf-dist/doc/man/man1/afm2afm.1
    trunk/Master/texmf-dist/doc/man/man1/afm2afm.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/autoinst.1
    trunk/Master/texmf-dist/doc/man/man1/autoinst.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1
    trunk/Master/texmf-dist/doc/man/man1/ot2kpx.man1.pdf
    trunk/Master/texmf-dist/doc/support/fontools/README
    trunk/Master/texmf-dist/scripts/fontools/afm2afm
    trunk/Master/texmf-dist/scripts/fontools/autoinst
    trunk/Master/texmf-dist/scripts/fontools/ot2kpx

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/support/fontools/splitttc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t3.enc
    trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ts3.enc

Modified: trunk/Build/source/texk/texlive/linked_scripts/fontools/afm2afm
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/fontools/afm2afm	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Build/source/texk/texlive/linked_scripts/fontools/afm2afm	2019-06-26 20:41:25 UTC (rev 51473)
@@ -37,7 +37,7 @@
 use Getopt::Long;
 use Pod::Usage;
 
-my $VERSION = "20190522";
+my $VERSION = "20190625";
 
 parse_commandline();
 
@@ -75,7 +75,7 @@
 sub parse_commandline {
     Getopt::Long::GetOptions(
         'help|?'     =>  sub { pod2usage(-verbose => 1) },
-        'version'    =>  sub { print "$VERSION\n"; exit; },
+        'version'    =>  sub { print "$VERSION\n"; exit },
         'encoding=s' => \$ARGV{encoding},
         'kpx=s'      => \$ARGV{kpx},
         'output=s'   => \$ARGV{output},
@@ -321,10 +321,10 @@
 
 [B<-help>]
 [B<-version>]
-[B<-encoding> I<encodingfile>]
-[B<-kpx> I<kpxfile>]
-[B<-output> I<outputfile>]
-B<afmfile>
+[B<-encoding>=I<< <encodingfile> >>]
+[B<-kpx>=I<< <kpxfile> >>]
+[B<-output>=I<< <outputfile> >>]
+B<< <afmfile> >>
 
 =back
 
@@ -360,28 +360,28 @@
 
 Print version number and exit
 
-=item B<-encoding> I<encodingfile>
+=item B<-encoding>=I<< <encodingfile> >>
 
-Re-encode to the enconding in I<encodingfile>
+Re-encode to the enconding in I<< <encodingfile> >>
 
-=item B<-kpx> I<kpxfile>
+=item B<-kpx>=I<< <kpxfile> >>
 
-Read additional kerning pairs from I<kpxfile> and add these to the output.
+Read additional kerning pairs from I<< <kpxfile> >> and add these to the output.
 This option cannot be used to override values from the input F<afm> file,
 since B<afm2afm> will write both old and new values to the output!
 
-The I<kpxfile> should contain kerning data in standard F<afm> format,
+The I<< <kpxfile> >> should contain kerning data in standard F<afm> format,
 i.e. for each kerning pair there should be a line
 
     KPX <left_glyph> <right_glyph> <amount>
 
-All other lines in the I<kpxfile> are ignored.
+All other lines in the I<< <kpxfile> >> are ignored.
 
-=item B<-output> I<outputfile>
+=item B<-output>=I<< <outputfile> >>
 
-Write the result to I<outputfile> instead of C<stdout>.
+Write the result to I<< <outputfile> >> instead of C<stdout>.
 
-=item B<afmfile>
+=item B<< <afmfile> >>
 
 The F<afm> file to be re-encoded.
 
@@ -421,7 +421,7 @@
 
 =head1 VERSION
 
-This document describes B<afm2afm> version 20190522.
+This document describes B<afm2afm> version 20190625.
 
 
 =head1 RECENT CHANGES

Modified: trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Build/source/texk/texlive/linked_scripts/fontools/autoinst	2019-06-26 20:41:25 UTC (rev 51473)
@@ -40,7 +40,7 @@
 use Pod::Usage ();
 use POSIX ();
 
-my $VERSION = '20190522';
+my $VERSION = '20190625';
 
 my ($d, $m, $y) = (localtime time)[3 .. 5];
 my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d;
@@ -50,34 +50,48 @@
     Some fontnames contain abbreviated words for width, weight and/or shape;
     we unabbreviate these using the following table.
 
+    To avoid having to have this information in multiple places,
+    we also build a reversed table %ABBREV that maps 'full' forms
+    to all known abbreviations; we then inject these abbreviations into
+    the %NFSS_WEIGHT, %NFSS_WIDTH and %NFSS_SHAPE tables below,
+    so that they recognise the abbreviated forms as well as the full ones.
+
 =end Comment
 
 =cut
 
 my %UNABBREVIATE = (
-    demi    =>  'demibold',
-    hair    =>  'hairline',
-    ultra   =>  'ultrablack',
     cmp     =>  'compressed',
     comp    =>  'compressed',
     cond    =>  'condensed',
+    demi    =>  'demibold',
+    extcond =>  'extracondensed',
+    hair    =>  'hairline',
+    incline =>  'inclined',
     it      =>  'italic',
     ita     =>  'italic',
+    md      =>  'medium',
     slant   =>  'slanted',
-    incline =>  'inclined',
+    ultra   =>  'ultrablack',
 );
+my %ABBREV;
+while ( my ($k, $v) = each %UNABBREVIATE ) {
+    push @{$ABBREV{$v}}, $k;
+}
+for my $full (keys %ABBREV) {
+    push @{$ABBREV{$full}}, $full;
+}
 
 =begin Comment
 
-    LaTeX's NFSS contains a limited number of standard codes for weight and width:
+    LaTeX's NFSS contains a number of standard codes for weight and width:
     - weight: ul, el, l, sl, m, sb, b, eb, ub
     - width:  uc, ec, c, sc, m, sx, x, ex, ux
 
-    These codes are not always a good match with the weights and widths
-    actually present in a font family; some families (especially sans-serif ones)
-    contain too many weights and widths, and the naming of those weights and
-    widths isn't always consistent between font families.
-
+    These codes are not always a perfect match with the weights and widths
+    present in a font family; some families (especially sanserif ones)
+    contain more or different weights and widths, and the naming of those
+    weights and widths isn't always consistent between font families.
     To handle this situation, we use a two-tiered approach:
     1.  We install all fonts using a "series" name that is the concatenation
         of whatever the font designer has chosen to call the weight and width
@@ -94,91 +108,75 @@
 
         sc  =>  [ qw( semicondensed narrow ) ],
 
-    This should be read as follows: the NFSS code "sc" is mapped to the *first*
-    width on the right hand side that is present in the current font family.
+    This should be read as follows: the NFSS code "sc" is mapped to
+    the *first* width on the right hand side present in the current family.
 
-    Please note that the tables contain empty keys instead of "m" for
-    the regular weight and width. NFSS actually combines weight and width
-    into a single "series" attribute; a weight or width of "m" is left out of
+    Please note that the tables contain empty keys instead of "m" for the
+    regular weight and width. NFSS actually combines weight and width into
+    a single "series" attribute; a weight or width of "m" is left out of
     this combination (unless *both* weight and width are equal to "m"; then
     the series becomes "m", but that's a special case we deal with later on).
 
     In addition to the mapping of NFSS codes, the two mentioned tables are
-    also used in parsing the font's metadata to determine its weight and width:
-    any string that occurs on the right hand side is considered a possible name
-    to be searched for.
+    also used in parsing the font's metadata to determine its weight and
+    width: any string that occurs on the right hand side is considered a
+    possible name to be searched for.
 
-    These tables can be extended to teach autoinst about new weights or widths.
-    Suppose your font family contains a "Hemibold" weight. Then add the name
-    "hemibold" to the right hand side of the "sb" entry in the NFSS_WEIGHT
-    table:
+    These tables can be extended to teach autoinst about new weights or
+    widths.  Suppose your font family contains a "Hemibold" weight, that
+    you want mapped to the "sb" code. Then add the name "hemibold" to
+    the right hand side of the "sb" entry in the NFSS_WEIGHT table:
 
         sb  =>  [ qw( semibold demi demibold medium hemibold ) ],
 
-    In this case, since it's in last position, it's only mapped to "sb" if none of
-    the other fonts are present. Put it earlier in the list to give it higher
-    priority (or put it in another entry if you'd rather see it mapped to another
-    NFSS code).
+    In this case, since it's in last position, it's only mapped to "sb"
+    if none of the other fonts are present. Put it earlier in the list
+    to give it higher priority.
 
-    Note that autoinst converts all metadata to lowercase to avoid inconsistent
-    capitalization; so all entries in these tables should be *lowercase* as well.
+    Note that autoinst converts all metadata to lowercase to avoid
+    inconsistent capitalization; so all entries in these tables should
+    be *lowercase* as well.
 
-    Technical note:
-    We define NFSS_WEIGHT and NFSS_WIDTH first as arrays and then as hashtables;
-    this allows us to use the array-variants as an *ordered* list of keys.
+    Technical notes:
+    -   We define NFSS_WEIGHT and NFSS_WIDTH first as arrays
+        and then as hashtables; this allows us to use the array-variants
+        as an *ordered* (by weight/width) list of values.
+    -   We exclude the Medium and Regular weights and widths
+        from the @WEIGHTS and @WIDTHS arrays to avoid false positives;
+        see the comments in the parse_basicinfo() function.
 
-
-    Finally, some random remarks about these tables:
-    - Poster and Super aren't just "very heavy" weights; in most cases, they're
-        more like separate designs. The same holds for the Compact width.
-        I added them for completeness.
-    - Two, Four and Eight are (experimental) weights that only occur in Fira Sans.
-    - Some families (Helvetica, Univers) treat Thin as a synonym for Extralight;
-        mostly, however, it is a very light weight below Ultralight.
-    - Semilight weights are virtually nonexistent, except for Thesis
-        (which contains a Semilight weight) and Arnhem (which has Blond).
-    - Book is usually slightly lighter than Regular, but sometimes
-        (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
-    - Likewise, Medium can really be two different things:
-        - a synonym for Semibold
-        - (especially in newer fonts) an extra step between Regular and Semibold
-        I treat it as if it's always the first.
-    - Heavy can mean very different things; it's often heavier than Black,
-        but sometimes it's a synonym for Extrabold, and in Futura it's even
-        lighter than Bold. I treat it here as "very black".
-    - Font families that have both Condensed and Compressed widths
-        seem to define Compressed as narrower than Condensed.
-    - In Basic Sans and Input (which are the only families I know with both
-        Narrow and Condensed), Narrow is a bit wider than Condensed.
-        So I mapped Narrow to "sc".
-    - Extended and Expanded seem to be used interchangeably.
-    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts,
-        so the ex and ux entries are currently empty.
-
 =end Comment
 
 =cut
 
 my @NFSS_WEIGHT = (
-    ul  =>  [ qw( ultralight thin hair hairline eight four two ) ],
+    ul  =>  [ qw( ultralight thin hairline eight four two ) ],
     el  =>  [ qw( extralight ) ],
     l   =>  [ qw( light ) ],
     sl  =>  [ qw( semilight blond ) ],
     ''  =>  [ qw( regular text book ) ],
-    sb  =>  [ qw( semibold demi demibold medium ) ],
+    sb  =>  [ qw( semibold demibold medium ) ],
     b   =>  [ qw( bold ) ],
     eb  =>  [ qw( extrabold ) ],
-    ub  =>  [ qw( ultrabold black heavy extrablack ultra ultrablack ultraheavy
-                  poster super ) ],
+    ub  =>  [ qw( ultrabold black heavy extrablack ultrablack
+                  ultraheavy poster super ) ],
 );
 my %NFSS_WEIGHT = @NFSS_WEIGHT;
 @NFSS_WEIGHT = grep { !ref } @NFSS_WEIGHT;
-my @WEIGHTS = map { @{$_} } values %NFSS_WEIGHT;
 
+# Add abbreviated forms, using the %ABBREV table constructed earlier
+for my $code (@NFSS_WEIGHT) {
+    $NFSS_WEIGHT{$code}
+        = [ map { @{ $ABBREV{$_} // [$_] } } @{$NFSS_WEIGHT{$code}} ];
+}
+
+my @WEIGHTS = grep { $_ !~ m/ regular | medium /xms }
+                   map { @{$_} } values %NFSS_WEIGHT;
+
 my @NFSS_WIDTH = (
     uc  =>  [ qw( ultracondensed extracompressed ultracompressed ) ],
-    ec  =>  [ qw( extracondensed cmp comp compressed compact ) ],
-    c   =>  [ qw( cond condensed ) ],
+    ec  =>  [ qw( extracondensed compressed compact ) ],
+    c   =>  [ qw( condensed ) ],
     sc  =>  [ qw( semicondensed narrow ) ],
     ''  =>  [ qw( regular ) ],
     sx  =>  [ qw( semiextended semiexpanded ) ],
@@ -188,8 +186,15 @@
 );
 my %NFSS_WIDTH = @NFSS_WIDTH;
 @NFSS_WIDTH = grep { !ref } @NFSS_WIDTH;
-my @WIDTHS = map { @{$_} } values %NFSS_WIDTH;
 
+# Add abbreviated forms, using the %ABBREV table constructed earlier
+for my $code (@NFSS_WIDTH) {
+    $NFSS_WIDTH{$code}
+        = [ map { @{ $ABBREV{$_} // [$_] } } @{$NFSS_WIDTH{$code}} ];
+}
+
+my @WIDTHS = grep { $_ ne 'regular' } map { @{$_} } values %NFSS_WIDTH;
+
 =begin Comment
 
     The NFSS_SHAPE table maps various shape names to NFSS codes.
@@ -200,8 +205,8 @@
     we might have multiple weighs or widths mapping to the same code,
     and we need a way to prioritise some weights/widths over others.
 
-    For shapes, that's not the case; font families don't have both Slanted and
-    Oblique shapes, since these are just different names for the same thing.
+    For shapes, that's not the case; font families don't have both Slanted
+    and Oblique shapes, since these are different names for the same thing.
 
     Like in the other NFSS_* tables, entries may be added to teach autoinst
     about new shapes.
@@ -214,19 +219,22 @@
     roman       =>  'n',
     upright     =>  'n',
     italic      =>  'it',
-    ita         =>  'it',
-    it          =>  'it',
     cursive     =>  'it',
     kursiv      =>  'it',
     inclined    =>  'sl',
-    incline     =>  'sl',
     oblique     =>  'sl',
     slanted     =>  'sl',
-    slant       =>  'sl',
-    romani      =>  'n',    # Silentium Pro has two roman shapes, but no italic;
-    romanii     =>  'it',   # so we cheat by mapping the second roman shape to 'it'
+    romani      =>  'n',    # Silentium has two roman shapes, but no italic;
+    romanii     =>  'it',   # so we cheat by mapping the second roman to 'it'
 );
 my %NFSS_SHAPE = @NFSS_SHAPE;
+for my $full (keys %ABBREV) {
+    if (defined $NFSS_SHAPE{$full}) {
+        for my $abbrev ( @{$ABBREV{$full}} ) {
+            $NFSS_SHAPE{$abbrev} = $NFSS_SHAPE{$full};
+        }
+    }
+}
 
 =begin Comment
 
@@ -319,8 +327,8 @@
 
     Each key in this table names a figure style; the corresponding
     value is an anonymous hash with four key/value pairs:
-        reqd    A list of required OpenType features;
-                this style is built if the font supports *all* these features.
+        reqd    A list of required OpenType features; this style is built
+                if the font supports *all* these features.
         nice    A list of optional OpenType features;
                 these are used if the font supports them, but don't
                 prevent this style from being built when missing.
@@ -458,6 +466,8 @@
     ARGV::parse_options();
 
     my @fonts = map { Fontinfo::parse_fontinfo($_) } @ARGV;
+
+    create_logfile(@fonts);
     Fontinfo::assert_unique(@fonts);
 
     # We can only handle the '-inferiors=auto' option now,
@@ -489,7 +499,7 @@
     # Decide to which weights and widths we'll map the standard NFSS codes
     decide_nfss_mappings(@fonts);
 
-    create_logfile(@worklist);
+    log_worklist(@worklist);
 
     if (!$ARGV{dryrun}) {
         # Create the LaTeX support files
@@ -513,8 +523,8 @@
 # Return a list with all unique entries from the input
 #-----------------------------------------------------------------------
 sub uniq {
-    my %tmp = map { ($_ => 1) } @_;
-    return keys %tmp;
+    my %seen;
+    return grep { !$seen{$_}++ } @_;
 }
 
 #-----------------------------------------------------------------------
@@ -597,21 +607,21 @@
 sub cleanup {
     my @worklist = @_;
 
+    WORKITEM:
     for my $item (@worklist) {
         my ($font, $style, $shape, $encoding)
             = @{$item}{qw(font style shape encoding)};
 
-        # make unique copy of fontdata, since we're modifying it;
-        # otherwise, the mergesmallcaps option only works for
-        # the first encoding in the list
-        my %font = %$font;
-        $font = $item->{font} = \%font;
-
-        # handle fonts that put small caps fonts into separate family
-        if ($ARGV{mergesmallcaps}) {
-            if ($font->{family} =~ s/(?: smallcaps | sc )$//xmsi) {
-                $shape = $item->{shape} = 'smallcaps';
+        # don't generate smallcaps version of TS1-encoded fonts,
+        # as these contain the same glyphs as the regular version
+        if ($font->{is_smallcaps}) {
+            if ($shape eq 'textcomp') {
+                $item = 0;
+                next WORKITEM;
             }
+            else {
+                $shape = 'smallcaps';
+            }
         }
 
         # generate unique name for this font
@@ -637,13 +647,14 @@
         $item->{features} = [ sort keys %feature ];
 
         # add finishing touches to name and NFSS code of encoding
-        $item->{encoding}[0] =~ s/\A (ot1|t1|ly1|lgr|t2[abc]) \z/fontools_$1/xms;
+        $item->{encoding}[0]
+            =~ s/\A (ot1|t1|ly1|lgr|t2[abc]|t3|ts3) \z/fontools_$1/xms;
         $item->{encoding}[1] = uc $item->{encoding}[1];
 
         $item->{cmdline} = make_cmdline($item);
     }
 
-    return @worklist;
+    return grep { $_ } @worklist;
 }
 
 #-----------------------------------------------------------------------
@@ -652,37 +663,65 @@
 sub decide_nfss_mappings {
     my ( %weight, %width );
     for my $font (@_) {
-        $weight{ $font->{weight} } = 1;
-        $width{ $font->{width} } = 1;
+        $weight{ $font->{weight} } //= $font->{weight_class};
+        $width{ $font->{width} } //= $font->{width_class};
     }
 
     NFSSWEIGHT:
     for my $nfssweight (@NFSS_WEIGHT) {
-        for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
-            if ( $weight{$weight} ) {
-                $NFSS_WEIGHT{$nfssweight} = [ $weight ];
-                next NFSSWEIGHT;
-            }
-        }
-        $NFSS_WEIGHT{$nfssweight} = [];
+        $NFSS_WEIGHT{$nfssweight}
+            = [ grep { $weight{$_} } @{$NFSS_WEIGHT{$nfssweight}} ];
     }
+
+    # Some trickery to handle the case where the ul/ub codes are mapped
+    # but the el/eb codes are still empty. We try two things:
+    # 1.  if there is a Thin (Heavy) weight and this is less extreme
+    #     than the weight mapped to ul (ub), we map Thin (Heavy) to ul (ub)
+    # 2.  otherwise we move the ul/ub weight to the el/eb position,
+    #     unless that weight is the Ultralight/Ultrabold weight
     if ( !$ARGV{el} and !$ARGV{ul} ) {
-        if ( @{$NFSS_WEIGHT{ul}}
-                and $NFSS_WEIGHT{ul}[0] ne 'ultralight'
-                and !@{$NFSS_WEIGHT{el}} ) {
-            $NFSS_WEIGHT{el} = $NFSS_WEIGHT{ul};
-            $NFSS_WEIGHT{ul} = [];
+        if ( @{$NFSS_WEIGHT{ul}} and !@{$NFSS_WEIGHT{el}} ) {
+            if ( $weight{thin}
+                    and $weight{thin} > $weight{$NFSS_WEIGHT{ul}[0]} ) {
+                $NFSS_WEIGHT{el} = [ 'thin', ];
+            }
+            elsif ( $NFSS_WEIGHT{ul}[0] ne 'ultralight' ) {
+                $NFSS_WEIGHT{el} = [ shift @{$NFSS_WEIGHT{ul}} ];
+            }
         }
     }
     if ( !$ARGV{eb} and !$ARGV{ub} ) {
-        if ( @{$NFSS_WEIGHT{ub}}
-                and $NFSS_WEIGHT{ub}[0] ne 'ultrabold'
-                and !@{$NFSS_WEIGHT{eb}} ) {
-            $NFSS_WEIGHT{eb} = $NFSS_WEIGHT{ub};
-            $NFSS_WEIGHT{ub} = [];
+        if ( @{$NFSS_WEIGHT{ub}} and !@{$NFSS_WEIGHT{eb}} ) {
+            if (    $weight{heavy}
+                and $weight{heavy} < $weight{$NFSS_WEIGHT{ub}[0]}
+            ) {
+                $NFSS_WEIGHT{eb} = [ 'heavy', ]
+                    unless @{$NFSS_WEIGHT{b}}
+                       and $weight{$NFSS_WEIGHT{b}[0]} > $weight{heavy};
+            }
+            elsif ( $NFSS_WEIGHT{ub}[0] ne 'ultrabold' ) {
+                $NFSS_WEIGHT{eb} = [ shift @{$NFSS_WEIGHT{ub}} ];
+            }
         }
     }
 
+    # Special case: if we don't have Regular but we *do* have Medium,
+    # move Medium from the "sb" list to the "m" (i.e., Regular) one.
+    if ( !@{$NFSS_WEIGHT{''}} and $weight{medium} ) {
+        $NFSS_WEIGHT{''} = [ 'medium' ];
+        $NFSS_WEIGHT{sb}
+            = [ grep { $_ ne 'medium' } @{$NFSS_WEIGHT{medium}} ];
+    }
+
+    # Some more trickery to map the sl code to Book or Text (but of course
+    # only if sl is empty and Book/Text is lighter than Regular)
+    if ( !@{$NFSS_WEIGHT{sl}} ) {
+        $NFSS_WEIGHT{sl}
+            = [ grep { $weight{$_} < $weight{$NFSS_WEIGHT{''}[0]} }
+                     @{$NFSS_WEIGHT{''}}
+            ];
+    }
+
     NFSSWIDTH:
     for my $nfsswidth (@NFSS_WIDTH) {
         for my $width ( @{$NFSS_WIDTH{$nfsswidth}} ) {
@@ -696,18 +735,14 @@
 }
 
 #-----------------------------------------------------------------------
-# Dump all relevant info to the logfile
+# Log all fonts, styles, encodings etc. we're  going to create
 #-----------------------------------------------------------------------
 sub create_logfile {
-    my @worklist
-        = sort { $a->{font}{filename} cmp $b->{font}{filename}
-                    || $a->{encoding}[1] cmp $b->{encoding}[1]
-                    || $a->{style} cmp $b->{style}
-               } @_;
+    my @fonts = @_;
 
     if (-e $ARGV{logfile}) {
-        print "[INFO]: file '$ARGV{logfile}' already exists;\n" .
-              "        appending new log data to end\n\n";
+        print "[INFO] file '$ARGV{logfile}' already exists;\n" .
+              "       appending new log data to end\n\n";
     }
     open my $LOG, '>>', $ARGV{logfile}
         or die "$0: cannot create $ARGV{logfile}: $!";
@@ -720,13 +755,10 @@
 
 @{[ POSIX::strftime("[%F %T]", localtime time) ]}  $0, version $VERSION
 
-
     "$ARGV{cmdline}"
 
-
 ----------------------------------------------------------------------------
 
-
 I'm using the following options:
 
     encoding(s):        @{[ join ', ', @{$ARGV{encoding}} ]}
@@ -755,17 +787,74 @@
     target:             $ARGV{target}
     extra:              @{[ $ARGV{extra} || '<empty>' ]}
 
-    figurekern:         @{[ $ARGV{figurekern}       ? 'no action' : 'remove' ]}
-    mergewidths:        @{[ $ARGV{mergewidths}      ? 'yes' : 'no' ]}
-    mergesmallcaps:     @{[ $ARGV{mergesmallcaps}   ? 'yes' : 'no' ]}
+    figurekern:         @{[ $ARGV{figurekern}   ? 'keep' : 'remove' ]}
+    mergewidths:        @{[ $ARGV{mergewidths}  ? 'yes' : 'no' ]}
+    mergeweights:       @{[ $ARGV{mergeweights} ? 'yes' : 'no' ]}
+    mergeshapes:        @{[ $ARGV{mergeshapes}  ? 'yes' : 'no' ]}
 
+    nfssweight:         @{[ join q{, }, @{$ARGV{nfssweight}} or '-' ]}
+    nfsswidth:          @{[ join q{, }, @{$ARGV{nfsswidth}}  or '-' ]}
 
-    font files:
-        @{[ join "\n        ", @ARGV ]}
-
 END_ARGUMENTS
 
-    printf {$LOG} "\n" . '-' x 76 . "\n\n\nNFSS mappings:\n\n";
+    my %fontfamilies = map { ( $_->{family} => 1 ) } @fonts;
+    my @fontfamilies = keys %fontfamilies;
+    if (scalar @fontfamilies > 1) {
+        warn <<"END_WARNING_MULTIPLE_FAMILIES";
+[WARNING] Your fonts seem to belong to multiple families:
+
+          @{[ join( "\n" . q{ } x 10, sort @fontfamilies ) ]}
+
+          "autoinst" performs best when installing one family at a time.
+          If you think your fonts should all be in the same family,
+          you might have found a bug in autoinst's font info parsing.
+
+          Please see the log file $ARGV{logfile} for details on how
+          the fonts' families, weights, widths and shapes were parsed.
+
+END_WARNING_MULTIPLE_FAMILIES
+
+        # increase verbosity if necessary, to log all relevant info
+        if ($ARGV{verbose} < 1) {
+            $ARGV{verbose} = 1;
+        }
+    }
+
+    $ARGV{logfile} = $LOG;
+
+    return if $ARGV{verbose} < 1;
+
+    print {$LOG} '-' x 76 . "\n\nResults of font info parsing:\n";
+
+    for my $font (@fonts) {
+        print {$LOG} <<"END_PARSE_FONT";
+
+    $font->{filename}
+        Name:       $font->{name}
+        Family:     $font->{family}
+        Weight:     $font->{weight} ($font->{weight_class})
+        Width:      $font->{width}
+        Shape:      $font->{shape} @{[ $font->{is_smallcaps}
+                                            ? '(smallcaps)' : '' ]}
+        Size:       $font->{minsize}-$font->{maxsize}
+        Features:   @{[ join ', ', sort keys %{$font->{feature}} ]}
+END_PARSE_FONT
+    }
+}
+
+#-----------------------------------------------------------------------
+# Log all fonts, styles, encodings etc. we're  going to create
+#-----------------------------------------------------------------------
+sub log_worklist {
+    my @worklist
+        = sort { $a->{font}{filename} cmp $b->{font}{filename}
+                    || $a->{encoding}[1] cmp $b->{encoding}[1]
+                    || $a->{style} cmp $b->{style}
+               } @_;
+
+    my $LOG = $ARGV{logfile};
+
+    print {$LOG} "\n" . '-' x 76 . "\n\nNFSS mappings:\n\n";
     for my $weight (@NFSS_WEIGHT) {
         printf {$LOG} "    %-3s =>  %s\n",
                 $weight || 'm', $NFSS_WEIGHT{$weight}[0] || '';
@@ -777,7 +866,7 @@
     }
     printf {$LOG} "\n";
 
-    return if $ARGV{Verbose} < 1;
+    return if $ARGV{verbose} < 1;
 
     my ($prevfn, $prevsty, $prevenc) = ('') x 3;
     my @cmds;
@@ -788,16 +877,7 @@
     ------------------------------------------------------------------------
 
     $item->{font}{filename}
-        Name:       $item->{font}{name}
-        Family:     $item->{font}{family}
-        Subfamily:  $item->{font}{subfamily}
-        Width:      $item->{font}{width}
-        Weight:     $item->{font}{weight}
-        Shape:      $item->{font}{shape}
-        Size:       $item->{font}{minsize}-$item->{font}{maxsize}
-        Features:   @{[ join ', ', sort keys %{$item->{font}{feature}} ]}
 
-
         Generating these encodings, figure styles and shapes:
 
         ENC     STYLE   SHAPE   FEATURES USED
@@ -808,11 +888,11 @@
             print {$LOG} "\n";
         }
         printf {$LOG} "        %-3s     %-4s    %-4s    %s\n",
-                            $item->{encoding}[1],
-                            $item->{style},
-                            $item->{fdshape},
-                            join(', ', @{$item->{features}}),
-                            ;
+                      $item->{encoding}[1],
+                      $item->{style},
+                      $item->{fdshape},
+                      join(', ', @{$item->{features}}),
+                      ;
         $prevfn  = $item->{font}{filename};
         $prevsty = $item->{style};
         $prevenc = $item->{encoding}[1];
@@ -820,7 +900,7 @@
         push @cmds, $item->{cmdline};
     }
 
-    return if $ARGV{Verbose} < 2;
+    return if $ARGV{verbose} < 2;
     print {$LOG} join "\n\n", @cmds;
     print {$LOG} "\n";
     close $LOG;
@@ -845,7 +925,14 @@
     }
     else {
         if (grep { system $_ } @commands) {
-            warn "[WARNING] 'otftotfm' returned non-zero; something's wrong!\n";
+            warn <<"END_OTFTOTFM_WARNING";
+[WARNING] one or more calls to 'otftotfm' failed;
+          please see the messages above.
+
+          Note that you can safely ignore any warnings
+              "bad UNICODING (‘germandbls’ has no encoding)"
+          or  "bad ligature (‘ff’ has no encoding)"
+END_OTFTOTFM_WARNING
         }
     }
 
@@ -862,6 +949,8 @@
     fontools_t2a => 'TEX CYRILLIC FONT ENCODING - T2A',
     fontools_t2b => 'TEX CYRILLIC FONT ENCODING - T2B',
     fontools_t2c => 'TEX CYRILLIC FONT ENCODING - T2C',
+    fontools_t3  => 'TEX IPA ENCODING',
+    fontools_ts3 => 'TEX IPA SYMBOL ENCODING',
 );
 
 #-----------------------------------------------------------------------
@@ -955,6 +1044,7 @@
     -(no)swash              Toggle creation of swash shape
     -(no)titling            Toggle creation of titling shape
     -(no)superiors          Toggle creation of fonts with superior characters
+    -noinferiors
     -inferiors=[none|auto|subs|sinf|dnom]
                             Use this style for subscripts (see docs)
     -(no)ornaments          Toggle creation of ornament fonts
@@ -978,8 +1068,9 @@
     -manual                 Manual mode (see documentation)
 
     -(no)figurekern         Keep or remove kerns between tabular figures
-    -(no)mergewidths        Merge Condended/Extended subfamilies with main family
-    -(no)mergesmallcaps     Merge small caps subfamilies with main family
+    -(no)mergewidths        Merge Condended/Extended subfamilies with main
+    -(no)mergeweights       Merge separate weights with main family
+    -(no)mergeshapes        Merge separate shapes with main family
 
     -nfssweight=xx=yyyy     Map the "xx" NFSS code to the "yyyy" weight
     -nfsswidth=xx=yyyy      Map the "xx" NFSS code to the "yyyy" width
@@ -987,8 +1078,8 @@
     -help                   Print this text and exit
     -doc                    Print the complete documentation and exit
     -dryrun                 Don't generate fonts, only log what would be done
-    -logfile="FILE"         Write log data to "FILE" (default: <fontfamily>.log)
-    -Verbose                Print more data to log file
+    -logfile="FILE"         Write log to "FILE" (default: <fontfamily>.log)
+    -verbose                Print more data to log file
                             (repeat for even higher verbosity)
     -version                Print version number and exit
     font[s]                 The fonts (.otf or .ttf format) to install.
@@ -999,7 +1090,7 @@
 # Default values for the command-line arguments
 %ARGV = (
     encoding        => 'OT1,T1,LY1',
-    textcomp        => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
+    textcomp        => '2',     # 0 = no, 1 = yes, 2 = ('T1' ? yes : no)
     lining          => '1',     # 0 = no, 1 = yes
     oldstyle        => '1',     # 0 = no, 1 = yes
     proportional    => '1',     # 0 = no, 1 = yes
@@ -1008,11 +1099,11 @@
     swash           => '1',     # 0 = no, 1 = yes
     titling         => '1',     # 0 = no, 1 = yes
     superiors       => '1',     # 0 = no, 1 = yes
-    inferiors       => 'none',  # possible values: none, auto, subs, sinf, dnom
+    inferiors       => 'none',  # values: none, auto, subs, sinf, dnom
     ornaments       => '1',     # 0 = no, 1 = yes
     fractions       => '0',     # 0 = no, 1 = yes
-    ligatures       => '2',     # 0 = no, 1 = yes, 2 = (nfss ne 'tt' ? yes : no)
-    nfss            => 'rm',
+    ligatures       => '2',     # 0 = no, 1 = yes, 2 = ('tt' ? no : yes)
+    nfss            => '',
     fig_height      => 'lnum',
     fig_width       => 'tnum',
     extra           => '',
@@ -1025,8 +1116,11 @@
     logfile         => '',
     figurekern      => '1',     # 0 = no, 1 = yes
     mergewidths     => '1',     # 0 = no, 1 = yes
-    mergesmallcaps  => '1',     # 0 = no, 1 = yes
-    Verbose         => 0,
+    mergeweights    => '1',     # 0 = no, 1 = yes
+    mergeshapes     => '1',     # 0 = no, 1 = yes
+    verbose         => 0,
+    nfsswidth       => [],
+    nfssweight      => [],
 );
 
 #-----------------------------------------------------------------------
@@ -1036,9 +1130,9 @@
     $ARGV{cmdline} = join ' ', ($0, @ARGV);
 
     Getopt::Long::GetOptions(
-        'help|?'              =>  sub { print $USAGE; exit; },
-        'version'             =>  sub { print "$VERSION\n"; exit; },
-        'doc'                 =>  sub { Pod::Usage::pod2usage(-Verbose => 2); },
+        'help|?'              =>  sub { print $USAGE; exit },
+        'version'             =>  sub { print "$VERSION\n"; exit },
+        'doc'                 =>  sub { Pod::Usage::pod2usage(-verbose => 2) },
         'encoding=s'          => \$ARGV{encoding},
         'ts1!'                => \$ARGV{textcomp},
         'lining!'             => \$ARGV{lining},
@@ -1049,7 +1143,8 @@
         'swash!'              => \$ARGV{swash},
         'titling!'            => \$ARGV{titling},
         'superiors!'          => \$ARGV{superiors},
-        'inferiors=s'         => \$ARGV{inferiors},
+        'noinferiors'         =>  sub { $ARGV{inferiors} = 'none' },
+        'inferiors:s'         => \$ARGV{inferiors},
         'ornaments!'          => \$ARGV{ornaments},
         'fractions!'          => \$ARGV{fractions},
         'ligatures!'          => \$ARGV{ligatures},
@@ -1069,19 +1164,29 @@
         'manual'              => \$ARGV{manual},
         'figurekern!'         => \$ARGV{figurekern},
         'mergewidths!'        => \$ARGV{mergewidths},
-        'mergesmallcaps!'     => \$ARGV{mergesmallcaps},
+        'mergeweights!'       => \$ARGV{mergeweights},
+        'mergeshapes!'        => \$ARGV{mergeshapes},
+        'mergesmallcaps!'     => \$ARGV{mergeshapes},
         'logfile=s'           => \$ARGV{logfile},
-        'Verbose+'            => \$ARGV{Verbose},
+        'verbose+'            => \$ARGV{verbose},
         'nfssweight=s%'       => sub {
                                      my ( $ignored, $key, $values ) = @_;
+                                     push @{$ARGV{nfssweight}},
+                                          "$key=$values";
                                      my @values = split m/,/, lc $values;
-                                     $NFSS_WEIGHT{$key} = \@values;
+                                     $key = q{} if $key eq 'm';
+                                     $NFSS_WEIGHT{$key}
+                                         = [ @values, @{$NFSS_WEIGHT{$key}} ];
                                      $ARGV{$key} = 'user-defined';
                                  },
         'nfsswidth=s%'        => sub {
                                      my ( $ignored, $key, $values ) = @_;
                                      my @values = split m/,/, lc $values;
-                                     $NFSS_WIDTH{$key} = \@values;
+                                     push @{$ARGV{nfsswidth}},
+                                          "$key=$values";
+                                     $key = q{} if $key eq 'm';
+                                     $NFSS_WIDTH{$key}
+                                         = [ @values, @{$NFSS_WIDTH{$key}} ];
                                      $ARGV{$key} = 'user-defined';
                                  },
     )
@@ -1096,6 +1201,7 @@
     delete $STYLE{Sup}           unless $ARGV{superiors};
     delete $STYLE{Orn}           unless $ARGV{ornaments};
     delete @STYLE{qw(Numr Dnom)} unless $ARGV{fractions};
+    $ARGV{inferiors} ||= 'auto';
     if    ($ARGV{inferiors} eq 'auto') { $STYLE{Inf}{reqd} = ['auto'] }
     elsif ($ARGV{inferiors} eq 'subs') { $STYLE{Inf}{reqd} = ['subs'] }
     elsif ($ARGV{inferiors} eq 'sinf') { $STYLE{Inf}{reqd} = ['sinf'] }
@@ -1120,6 +1226,25 @@
         delete $SHAPE{textcomp};
     }
 
+    # Determine NFSS classification of this family, if the user
+    # didn't explicitly specify it
+    if ( !$ARGV{nfss} ) {
+        # EXPERIMENTAL: parse "post" table to see if font is fixed-width
+        open my $otfinfo, '-|:raw', qq(otfinfo --dump-table 'post' "$ARGV[0]")
+            or die "[ERROR] could not fork(): $!";
+        my $post_table = do { local $/; <$otfinfo> };
+        close $otfinfo
+            or die "[ERROR] 'otfinfo --dump-table post $ARGV[0]' failed";
+
+        my $is_fixed_pitch = unpack '@12N', $post_table;
+
+        $ARGV{nfss} = $is_fixed_pitch                 ? 'tt'
+                    : $ARGV[0] =~ m/mono(?!type)/xmsi ? 'tt'
+                    : $ARGV[0] =~ m/sans/xmsi         ? 'sf'
+                    :                                   'rm'
+                    ;
+    }
+
     # If the user didn't explicitly say anything about ligatures,
     # activate them unless the font is a typewriter font.
     if ($ARGV{ligatures} == 2) {
@@ -1205,12 +1330,13 @@
     my ($filename) = @_;
 
     my $info = {
-        filename  => $filename,
-        width     => 'regular',
-        weight    => 'regular',
-        shape     => 'roman',
-        minsize   => 0,
-        maxsize   => 0,
+        filename     => $filename,
+        width        => 'regular',
+        weight       => 'regular',
+        shape        => 'roman',
+        minsize      => 0,
+        maxsize      => 0,
+        is_smallcaps => 0,
     };
 
     parse_basicinfo($info);
@@ -1230,7 +1356,7 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --info "$info->{filename}")
-        or die "[ERROR] 'otfinfo --info $info->{filename}' failed";
+        or die "[ERROR] could not fork(): $!";
     my %data = map { my ($k,$v) = m/\A\s* ([^:]+?) \s*:\s* ([^\r\n]+)/xms;
                      $k =~ s/\s+//xmsg;
                      $v =~ s/\s+//xmsg;
@@ -1237,7 +1363,8 @@
                      (lc $k => $v);
                    }
                    grep { m/\A\s* [^:]+? \s*:\s* [^\r\n]+/xms } <$otfinfo>;
-    close $otfinfo;
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --info $info->{filename}' failed";
 
     $data{family}    =  $data{preferredfamily} || $data{family};
     $data{subfamily} =  $data{preferredsubfamily} || $data{subfamily};
@@ -1246,33 +1373,47 @@
 
     # clean up family name (it's used in LaTeX command names)
     $data{family}    =~ s/\A(?: Adobe | DTL | FF | ITC | LT | MT)//xms;
+    $data{family}    =~ s/(?: LT | MT)(?: Std | Pro )\z//xms;
+    $data{family}    =~ s/(?<= Kievit ) OT//xms;
+    $data{family}    =~ s/ Std \z//xms;
     $data{family}    =~ s/(\d)/$DIGITS[$1]/xmsge;
     $data{family}    =~ s/[^A-Za-z]+//xmsg;
 
-    my $fullinfo =  lc "$data{subfamily} | $data{fullname}";
+    # Sometimes the relevant info is in Fullname, sometimes in Subfamily;
+    # so we need to test against both
+    my $fullinfo = lc "$data{subfamily} | $data{fullname}";
 
     # We need to be careful when parsing the font info; in particular
     # we must parse 'UltraCondensed' as 'Regular' weight
     # and 'UltraCondensed' width, not as 'Ultra' weight and 'Condensed' width.
-    # The following two rules should prevent accidents:
+    # The following rules should prevent accidents:
     # 1.  Search for matching widths before matching weights
     #     (as none of the widths is a proper substring of some weight)
     # 2.  Remove any recognised search string from the 'fullinfo'
+    # 3.  Test the weights 'medium' and 'regular' *last*, since these strings
+    #     may also occur in Subfamily without indicating the weight;
+    #     so we only take them to mean weight if we find no other hit.
     for my $width ( mqrs(@WIDTHS) ) {
-        if ($fullinfo =~ s/${width}//gxmsi) {
+        if ($fullinfo =~ m/${width}/xms) {
             $info->{width} = $width;
+            my $widths = join '|', mqrs(@WIDTHS);
+            $fullinfo =~ s/${widths}//gxmsi;
             last;
         }
     }
-    for my $weight ( mqrs(@WEIGHTS) ) {
-        if ($fullinfo =~ s/${weight}//gxmsi) {
+    for my $weight ( mqrs(@WEIGHTS), qw(medium regular) ) {
+        if ($fullinfo =~ m/${weight}/xms) {
             $info->{weight} = $weight;
+            my $weights = join '|', mqrs(@WEIGHTS), qw(medium regular);
+            $fullinfo =~ s/${weights}//gxmsi;
             last;
         }
     }
     for my $shape ( mqrs( keys %NFSS_SHAPE ) ) {
-        if ($fullinfo =~ s/${shape}//gxmsi) {
+        if ($fullinfo =~ m/${shape}/xms) {
             $info->{shape} = $shape;
+            my $shapes = join '|', mqrs( keys %NFSS_SHAPE );
+            $fullinfo =~ s/${shapes}//gxmsi;
             last;
         }
     }
@@ -1284,26 +1425,10 @@
     $data{subfamily} =~ s/$info->{weight}//xmsi;
     $data{subfamily} =~ s/$info->{shape}//xmsi;
 
-
     $info->{name}      = $data{postscriptname};
     $info->{family}    = $data{family};
     $info->{subfamily} = $data{subfamily};
 
-    if ( !$ARGV{logfile} ) {
-        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
-    }
-    # Some font families put condensed or extended widths into separate families;
-    # we provide an option to merge these with the 'main' font family.
-    if ($ARGV{mergewidths}) {
-        my $widths = join '|', mqrs(@WIDTHS);
-        if ($info->{width} eq 'regular'
-            && $info->{family} =~ m/(.+?) [ ]* (${widths})$/xmsi)
-        {
-            $info->{family} = $1;
-            $info->{width}  = lc $2;
-        }
-    }
-
     # Take care to unabbreviate weight and width; CondensedUltra fonts
     # might end up as 'ultracondensed' instead of 'ultrablackcondensed'!
     if (exists $UNABBREVIATE{ $info->{width} }) {
@@ -1316,16 +1441,81 @@
         $info->{shape} = $UNABBREVIATE{ $info->{shape} };
     }
 
+    if ($ARGV{mergeshapes}) {
+        my $shapes = join '|', mqrs( qw(it italic) );
+        if ( $info->{family} =~ m/(.+?) (${shapes}) \z/xmsi
+                and ( $info->{shape} eq 'regular'
+                   or $info->{shape} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{shape}  = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+
+        $shapes = join '|', mqrs( qw(sc smallcaps) );
+        if ( $info->{family} =~ m/(.+?) (${shapes}) \z/xmsi ) {
+            $info->{family}       = $1;
+            $info->{is_smallcaps} = 1;
+        }
+    }
+
+    # Some font families put different widths into separate families;
+    # we provide an option to merge these with the 'main' font family.
+    if ($ARGV{mergewidths}) {
+        my $widths = join '|', mqrs(@WIDTHS);
+        if ( $info->{family} =~ m/(.+?) (${widths}) \z/xmsi
+                and ( $info->{width} eq 'regular'
+                   or $info->{width} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{width}  = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+    }
+
+    # Some font families put extreme weights into separate families;
+    # we provide an option to merge these with the 'main' font family.
+    if ($ARGV{mergeweights}) {
+        my $weights = join '|', mqrs(@WEIGHTS), qw(medium regular);
+        if ( $info->{family} =~ m/(.+?) (${weights}) \z/xmsi
+                and ( $info->{weight} eq 'regular'
+                   or $info->{weight} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{weight} = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+    }
+
+    # Fix confusion about "Text": weight vs part of familyname.
+    # In the latter case, we strip it off anyway.
+    $info->{family} =~ s/text \z//xmsi;
+
+    if ( !$ARGV{logfile} ) {
+        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
+    }
+
     $info->{basicshape} = $NFSS_SHAPE{$info->{shape}};
 
-    # We define 'series' as 'weight + width'. This matches NFSS, but contradicts
-    # how most fonts are named (which is 'width + weight').
+    # We define 'series' as 'weight + width'. This matches NFSS,
+    # but contradicts how most fonts are named (which is 'width + weight').
     $info->{series}
-        = ($info->{width} eq 'regular')  ? $info->{weight}
+        = ($info->{width}  eq 'regular') ? $info->{weight}
         : ($info->{weight} eq 'regular') ? $info->{width}
         :                                  $info->{weight} . $info->{width}
         ;
 
+    # EXPERIMENTAL: we extract the usWeightClass and usWidthClass
+    # properties from the font's OS/2 table
+    open $otfinfo,
+         '-|:raw',
+         qq(otfinfo --dump-table 'OS/2' "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    my $os2_table = do { local $/; <$otfinfo> };
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --dump-table $info->{filename}' failed";
+    @{$info}{qw(weight_class width_class)} = unpack '@4n @6n', $os2_table;
+
     return;
 }
 
@@ -1332,7 +1522,8 @@
 #-----------------------------------------------------------------------
 # Re-order argument list so that longer strings come before shorter ones
 #
-# This is needed when matching a string against a list of patterns;
+# This is needed when matching a string against a list of patterns
+# where some of the patterns may be substrings of other patterns;
 # then we want the *longest* matching pattern, so we test the patterns
 # in descending order of length.
 #-----------------------------------------------------------------------
@@ -1348,14 +1539,16 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --features "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    %{$info->{feature}} = map { (substr($_, 0, 4) => 1) } <$otfinfo>;
+    close $otfinfo
         or die "[ERROR] 'otfinfo --features $info->{filename}' failed";
-    %{$info->{feature}} = map { (substr($_, 0, 4) => 1) } <$otfinfo>;
-    close $otfinfo;
 
     open $otfinfo, '-|', qq(otfinfo --tables "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
+    close $otfinfo
         or die "[ERROR] 'otfinfo --tables $info->{filename}' failed";
-    $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
-    close $otfinfo;
 
     return;
 }
@@ -1368,11 +1561,12 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --optical-size "$info->{filename}")
-        or die "[ERROR] 'otfinfo --optical-size $info->{filename}' failed";
+        or die "[ERROR] could not fork(): $!";
 
-    if (my ($minsize, $maxsize) = <$otfinfo> =~ m/[(] ([\d.]+) \s* pt, \s*
-                                              ([\d.]+) \s* pt  \s* []]/xms )
-    {
+    if (my ($minsize, $maxsize)
+        = <$otfinfo> =~ m/[(] ([\d.]+) \s* pt, \s*
+                              ([\d.]+) \s* pt  \s* []]/xms
+    ) {
     # fix some known bugs
         if ($info->{name} eq 'GaramondPremrPro-It'
             && $minsize == 6 && $maxsize == 8.9)
@@ -1400,7 +1594,8 @@
 
         @{$info}{qw(minsize maxsize)} = ($minsize, $maxsize);
     }
-    close $otfinfo;
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --optical-size $info->{filename}' failed";
 
     return;
 }
@@ -1441,7 +1636,8 @@
     my @fonts = @_;
 
     # These attributes should uniquely identify each font
-    my @attributes = qw(family weight width shape minsize maxsize);
+    my @attributes
+        = qw(family weight width shape minsize maxsize is_smallcaps);
 
     my (%seen, $err_details);
     for my $font (@fonts) {
@@ -1479,10 +1675,11 @@
         # Default ornament names: 'orn.' plus three digits
         my @encoding = map { sprintf "orn.%03d", $_ } 1 .. 256;
 
-        open my $OTFINFO, '-|', qq(otfinfo --glyphs "$font->{filename}")
+        open my $otfinfo, '-|', qq(otfinfo --glyphs "$font->{filename}")
+            or die "[ERROR] could not fork(): $!";
+        chop(my @glyphnames = <$otfinfo>);
+        close $otfinfo
             or die "[ERROR] 'otfinfo --glyphs $font->{filename}' failed";
-        chop(my @glyphnames = <$OTFINFO>);
-        close $OTFINFO;
 
         # Test for some known alternative names (probably not exhaustive)
         my @ornaments
@@ -1907,8 +2104,9 @@
 
 =item -
 
-Four text families (with lining and oldstyle digits, each in both tabular
-and proportional variants), all with the following shapes:
+Four text families (with lining and oldstyle digits,
+each in both tabular and proportional variants),
+all with the following shapes:
 
 =over 2
 
@@ -1944,8 +2142,8 @@
 
 =item -
 
-For each T1-encoded text family: a family of TS1-encoded symbol fonts,
-in roman, italic and slanted shapes.
+For each T1-encoded text family:
+a family of TS1-encoded symbol fonts, in roman, italic and slanted shapes.
 
 =item -
 
@@ -1954,7 +2152,8 @@
 
 =item -
 
-Families with "Titling" characters; these "... replace the default glyphs
+Families with "Titling" characters;
+these "... replace the default glyphs
 with corresponding forms designed specifically for titling.
 These may be all-capital and/or larger on the body,
 and adjusted for viewing at larger sizes"
@@ -2038,16 +2237,16 @@
 see the I<-logfile> command-line option in L</"COMMAND-LINE OPTIONS"> below.
 If this log file already exists, B<autoinst> will append its data to the end
 rather than overwrite it.
-Use the I<-Verbose> command-line option to ask for more detailed info.
+Use the I<-verbose> command-line option to ask for more detailed info.
 
 
 =head2 A note for MiKTeX users
 
 Automatically installing the fonts into a suitable TEXMF tree
-(as B<autoinst> tries to do by default) only works for TeX-installations that use
-the F<kpathsea> library; with TeX distributions that implement their
-own directory searching (such as MiKTeX), B<autoinst> will complain that
-it cannot find the F<kpsewhich> program and move all generated files
+(as B<autoinst> tries to do by default) only works for TeX-installations
+that use the F<kpathsea> library; with TeX distributions that implement
+their own directory searching (such as MiKTeX), B<autoinst> will complain
+that it cannot find the F<kpsewhich> program and move all generated files
 into a subdirectory C<./autoinst_output/> of the current directory.
 If you use such a TeX distribution, you should either move these files
 to their correct destinations by hand, or use the I<-target> option
@@ -2061,11 +2260,11 @@
 
 =head2 A note for MacTeX users
 
-By default, B<autoinst> will try to install all files into the $TEXMFLOCAL tree;
-when this directory isn't user-writable, it will use the $TEXMFHOME tree instead.
-Unfortunately, MacTeX's version of C<updmap-sys>
-(which is called behind the scenes) doesn't search in $TEXMFHOME,
-and hence MacTeX will not find the new fonts.
+By default, B<autoinst> will try to install all generated files into
+the $TEXMFLOCAL tree; when this directory isn't user-writable,
+it will use the $TEXMFHOME tree instead.  Unfortunately, MacTeX's version
+of C<updmap-sys> (which is called behind the scenes) doesn't search
+in $TEXMFHOME, and hence MacTeX will not find the new fonts.
 
 To remedy this, either run B<autoinst> as root (so that it can install
 everything into $TEXMFLOCAL) or manually run C<updmap -user> to tell
@@ -2077,8 +2276,8 @@
 =head2 Using the fonts in your LaTeX documents
 
 B<autoinst> generates a style file for using the fonts in LaTeX documents,
-named F<< <FontFamily>.sty >>. This style file also takes care of loading the
-F<fontenc> and F<textcomp> packages.
+named F<< <FontFamily>.sty >>. This style file also takes care of loading
+the F<fontenc> and F<textcomp> packages.
 To use the fonts, add the command C<<< \usepackage{I<< <FontFamily> >>} >>>
 to the preamble of your document.
 
@@ -2125,7 +2324,7 @@
 you have the F<mweights> package installed.
 
 The style file will also try to load the F<fontaxes> package
-(available on CTAN), which gives easy access to various font shapes and styles.
+(on CTAN), which gives easy access to various font shapes and styles.
 Using the machinery set up by F<fontaxes>, the generated style file
 defines a number of commands (which take the text to be typeset as argument)
 and declarations (which don't take arguments, but affect all text up to
@@ -2141,8 +2340,8 @@
 
 
 In addition, the C<\swshape> and C<\textsw> commands are redefined to place
-swash on F<fontaxes>' secondary shape axis (F<fontaxes> places it on the primary
-shape axis) to make them behave properly when nested, so that
+swash on F<fontaxes>' secondary shape axis (F<fontaxes> places it on the
+primary shape axis) to make them behave properly when nested, so that
 C<\swshape\upshape> will give upright swash.
 
 There are no commands for accessing the numerator and denominator
@@ -2159,8 +2358,8 @@
 To access ornament glyphs, B<autoinst> creates a font-specific encoding file
 F<< <FontFamily>_orn.enc >>,
 but only if that file doesn't yet exist in the current directory.
-This is a deliberate feature that allows you to provide your own
-encoding vector, e.g. if your fonts use non-standard glyph names for ornaments.
+This is a deliberate feature that allows you to provide your own encoding
+vector, e.g. if your fonts use non-standard glyph names for ornaments.
 
 These commands are only generated for existing shapes and number styles;
 no commands are generated for shapes and styles that don't exist,
@@ -2226,7 +2425,7 @@
 Of course, not all 81 combinations of these NFSS weights and widths will map
 to existing fonts;
 and conversely it may not be possible to assign every existing font
-a unique code in a sane way (especially on the weight axis, some font families
+a unique code in a sane way (especially for the weights, some font families
 offer more choices or finer granularity than NFSS's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional "Medium" weight between Regular and Semibold).
@@ -2279,7 +2478,7 @@
 If the file already exists, B<autoinst> appends to it;
 it doesn't overwrite an existing file.
 
-=item B<-Verbose> (I<note:> uppercase 'V'!)
+=item B<-verbose>
 
 Add more details to the log file. Repeat this option for even more info.
 
@@ -2294,17 +2493,17 @@
 The default choice of encodings is "OT1,T1,LY1".
 For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>!)
 should be somewhere where F<otftotfm> can find it. Suitable encoding files
-for OT1, T1/TS1, LY1, LGR and T2A/B/C come with B<autoinst>. (These files are
-called F<fontools_ot1.enc> etc. to avoid name clashes with other packages;
-the "fontools_" prefix may be omitted.)
+for OT1, T1/TS1, LY1, LGR, T2A/B/C and T3/TS3 come with B<autoinst>.
+(These files are called F<fontools_ot1.enc> etc. to avoid name clashes
+with other packages; the "fontools_" prefix may be omitted.)
 
-=item B<-ts1> / B<-nots1>
+=item B<-ts1>/B<-nots1>
 
 Control the creation of TS1-encoded fonts. The default is B<-ts1>
 if the text encodings (see I<-encoding> above) include T1,
 B<-nots1> otherwise.
 
-=item B<-serif> / B<-sanserif> / B<-typewriter>
+=item B<-serif>/B<-sanserif>/B<-typewriter>
 
 Install the font as a serif, sanserif or typewriter font, respectively.
 This changes how you access the font in LaTeX:
@@ -2318,46 +2517,55 @@
 This latter effect cannot be disabled in B<autoinst>;
 if you want typewriter text to be hyphenated, use the F<hyphenat> package.
 
-=item B<-lining> / B<-nolining>
+If none of these options is specified, B<autoinst> tries to guess:
+if the font's filename contains the string "mono"
+or if the field C<isFixedPitch> in the font's I<post> table is True,
+it will select B<-typewriter>;
+else if the filename contains "sans" it selects B<-sanserif>;
+and otherwise it will opt for B<-serif>.
 
+=item B<-lining>/B<-nolining>
+
 Control the creation of fonts with lining figures. The default is
 B<-lining>.
 
-=item B<-oldstyle> / B<-nooldstyle>
+=item B<-oldstyle>/B<-nooldstyle>
 
 Control the creation of fonts with oldstyle figures. The default is
 B<-oldstyle>.
 
-=item B<-proportional> / B<-noproportional>
+=item B<-proportional>/B<-noproportional>
 
 Control the creation of fonts with proportional figures. The default is
 B<-proportional>.
 
-=item B<-tabular> / B<-notabular>
+=item B<-tabular>/B<-notabular>
 
 Control the creation of fonts with tabular figures. The default is
 B<-tabular>.
 
-=item B<-smallcaps> / B<-nosmallcaps>
+=item B<-smallcaps>/B<-nosmallcaps>
 
 Control the creation of small caps fonts. The default is
 B<-smallcaps>.
 
-=item B<-swash> / B<-noswash>
+=item B<-swash>/B<-noswash>
 
 Control the creation of swash fonts. The default is B<-swash>.
 
-=item B<-titling> / B<-notitling>
+=item B<-titling>/B<-notitling>
 
 Control the creation of titling families. The default is B<-titling>.
 
-=item B<-superiors> / B<-nosuperiors>
+=item B<-superiors>/B<-nosuperiors>
 
 Control the creation of fonts with superior characters.
 The default is B<-superiors>.
 
-=item B<-inferiors>=[ B<none> | B<auto> | B<subs> | B<sinf> | B<dnom> ]
+=item B<-noinferiors>
 
+=item B<-inferiors> [= B<none> | B<auto> | B<subs> | B<sinf> | B<dnom> ]
+
 The OpenType standard defines several kinds of digits that might be used
 as inferiors or subscripts: "Subscripts" (OpenType feature "subs"),
 "Scientific Inferiors" ("sinf"), and "Denominators" ("dnom").
@@ -2365,31 +2573,33 @@
 should use for the inferior characters.
 Alternatively, the value "auto" tells B<autoinst> to use the first value
 in "subs", "sinf" or "dnom" that is supported by the font.
-The default value is "none".
+Saying just B<-inferiors> is equivalent to B<-inferiors=auto>;
+otherwise the default is B<-noinferiors>.
 
 I<< If you specify a style of inferiors that isn't present in the font,
 B<autoinst> will fall back to its default behaviour of not creating fonts
 with inferiors at all; it won't try to substitute one of the other styles. >>
 
-=item B<-fractions> / B<-nofractions>
+=item B<-fractions>/B<-nofractions>
 
 Control the creation of fonts with numerators and denominators.
 The default is B<-nofractions>.
 
-=item B<-ligatures> / B<-noligatures>
+=item B<-ligatures>/B<-noligatures>
 
 Some fonts create glyphs for the standard f-ligatures (ff, fi, fl, ffi, ffl),
 but don't provide a "liga" feature to access these.
 This option tells B<autoinst> to add extra C<LIGKERN> rules to
 the generated fonts to enable the use of these ligatures.
-The default is B<-ligatures>, unless the user specified the I<ligatures> option.
+The default is B<-ligatures>,
+unless the user specified the I<ligatures> option.
 
 Specify B<-noligatures> to disable the generation of ligatures even for fonts
 that do contain a "liga" feature.
 
-=item B<-defaultlining> / B<-defaultoldstyle>
+=item B<-defaultlining>/B<-defaultoldstyle>
 
-=item B<-defaulttabular> / B<-defaultproportional>
+=item B<-defaulttabular>/B<-defaultproportional>
 
 Tell B<autoinst> which figure style is the current font family's default
 (i.e., which figures you get when you don't specify any OpenType features).
@@ -2410,22 +2620,19 @@
 Note that this option leads to very long commands (it adds
 one hundred I< --ligkern> options), which may cause problems on some systems.
 
-=item B<-mergewidths> / B<-nomergewidths>
+=item B<-mergewidths>/B<-nomergewidths>,
+B<-mergeweights>/B<-nomergeweights>,
+B<-mergeshapes>/B<-nomergeshapes>
 
-Some font families put their Condensed, Narrow, Extended etc. widths
-in separate families;
-this option tells B<autoinst> to merge those separate families into
+Some font put different widths, weights or shapes (e.g., small caps)
+in separate families.
+These options tell B<autoinst> to merge those separate families into
 the main family.
-The default is B<-mergewidths>.
+Since this is usually desirable, they are all enabled by default.
 
-=item B<-mergesmallcaps> / B<-nomergesmallcaps>
+In earlier versions, B<-mergeshapes> was called B<-mergesmallcaps>;
+for reasons of backward compatibility, that option is still supported.
 
-Even more annoyingly, some font families put their small caps fonts
-in a separate family;
-this option tells B<autoinst> to merge the small caps fonts into
-the main family.
-The default is B<-mergesmallcaps>.
-
 =item B<-nfssweight>=I<code>=I<weight>, B<-nfsswidth>=I<code>=I<width>
 
 Map the NFSS code I<code> to the given weight or width,
@@ -2432,20 +2639,22 @@
 overriding the built-in tables.
 Each of these options may be given multiple times,
 to override more than one NFSS code.
-Example: to map the "ul" code to the "Thin" weight, use C<-nfssweight=ul=thin>.
-To inhibit the use of the "ul" code completely, use C<-nfssweight=ul=>.
+Example: to map the "ul" code to the "Thin" weight,
+use C<-nfssweight=ul=thin>.
+To inhibit the use of the "ul" code completely,
+use C<-nfssweight=ul=>.
 
 =item B<-extra>=I<text>
 
 Append I<text> as extra options to the command lines for I<otftotfm>.
-To prevent I<text> from accidentily being interpreted as options to B<autoinst>,
-it should be properly quoted.
+To prevent I<text> from accidentily being interpreted as options
+to B<autoinst>, it should be properly quoted.
 
 =item B<-manual>
 
-Manual mode; for users who want to post-process the generated files and commands.
-By default, B<autoinst> immediately executes all F<otftotfm> commands
-it generates;
+Manual mode; for users who want to post-process the generated files
+and commands. By default, B<autoinst> immediately executes all
+F<otftotfm> commands it generates;
 in manual mode, these are instead written to a file F<autoinst.bat>.
 Furthermore it tells F<otftotfm> to generate human readable (and editable)
 F<pl/vpl> files instead of the default F<tfm/vf> ones,
@@ -2457,19 +2666,19 @@
 
 =over 2
 
-=item B<-> run F<pltotf> and F<vptovf> on the generated F<pl> and F<vf> files,
+=item - run F<pltotf> and F<vptovf> on the generated F<pl> and F<vf> files,
 to convert them to F<tfm/vf> format;
 
-=item B<-> move all generated files to a proper TEXMF tree,
+=item - move all generated files to a proper TEXMF tree,
 and, if necessary, update the filename database;
 
-=item B<-> tell TeX about the new F<map> file
+=item - tell TeX about the new F<map> file
 (usually by running C<updmap> or similar).
 
 =back
 
-Note that some options (I<-target>, I<-vendor> and I<-typeface>, I<-[no]updmap>)
-are meaningless, and hence ignored, in manual mode.
+Note that some options (I<-target>, I<-vendor> and I<-typeface>,
+I<-[no]updmap>) are meaningless, and hence ignored, in manual mode.
 
 =item B<-target>=I<DIRECTORY>
 
@@ -2482,7 +2691,8 @@
 it will print a warning message and put all files into the subdirectory
 C<./autoinst_output/> of the current directory.
 It's then up to the user to move the generated files to a better location
-and update all relevant databases (usually by calling F<texhash> and F<updmap>).
+and update all relevant databases
+(usually by calling F<texhash> and F<updmap>).
 
 =item B<-vendor>=I<VENDOR>
 
@@ -2496,7 +2706,7 @@
 Note that these options change I<only> directory names,
 not the names of any generated files.
 
-=item B<-updmap> / B<-noupdmap>
+=item B<-updmap>/B<-noupdmap>
 
 Control whether or not F<updmap> is called after the last call to F<otftotfm>.
 The default is B<-updmap>.
@@ -2513,13 +2723,14 @@
 For Windows, try ActivePerl (F<http://www.activestate.com>)
 or Strawberry Perl (F<http://strawberryperl.com>).
 
-B<XeTeX> (F<http://www.tug.org/xetex>) and B<LuaTeX> (F<http://www.luatex.org>)
+B<XeTeX> (F<http://www.tug.org/xetex>) and
+B<LuaTeX> (F<http://www.luatex.org>)
 are Unicode-aware TeX engines that can use OpenType fonts directly,
 without any (La)TeX-specific support files.
 
 The B<FontPro> project (F<https://github.com/sebschub/FontPro>)
-offers very complete LaTeX support (even for typesetting maths) for Adobe's
-Minion Pro, Myriad Pro and Cronos Pro font families.
+offers very complete LaTeX support (even for typesetting maths) for
+Adobe's Minion Pro, Myriad Pro and Cronos Pro font families.
 
 
 =head1 AUTHOR
@@ -2526,9 +2737,9 @@
 
 Marc Penninga (F<marcpenninga at gmail.com>)
 
-When sending a bug report, please give as much relevant information as possible;
-this usually includes (but may not be limited to) the log file
-(please add the I<-Verbose> command-line option, for extra info).
+When sending a bug report, please give as much relevant information as
+possible; this usually includes (but may not be limited to) the log file
+(please add the I<-verbose> command-line option, for extra info).
 If you see any error messages, please include these I<verbatim>;
 don't paraphase.
 
@@ -2558,7 +2769,7 @@
 
 =head1 VERSION
 
-This document describes B<autoinst> version 20190522.
+This document describes B<autoinst> version 20190625.
 
 
 =head1 RECENT CHANGES
@@ -2567,12 +2778,56 @@
 
 =over 12
 
+=item I<2019-06-25>
+
+=over 3
+
+=item -
+
+Added the I<-mergeweights> and I<-mergeshapes> options,
+and improved I<-mergewidths>.
+
+=item -
+
+Improved the parsing of fonts' widths and weights.
+
+=item -
+
+Improved the mapping of widths and weights to NFSS codes.
+
+=item -
+
+Changed logging code so that that results of font info parsing
+are always logged, even (especially!) when parsing fails.
+
+=item -
+
+Added a warning when installing fonts from multiple families.
+
+=item -
+
+Added simple recognition for sanserif and typewriter fonts.
+
+=item -
+
+Fixed error checking after calls to F<otfinfo>
+(B<autoinst> previously only checked whether C<fork()> was successful,
+not whether the actual call to F<otfinfo> worked).
+
+=item -
+
+Fixed a bug in the I<-inferiors> option;
+when used without a (supposedly optional) value,
+it would silently gobble the next option instead.
+
+=back
+
 =item I<2019-05-22>
 
 Added the I<mainfont> option to the generated F<sty> files.
 Prevented hyphenation for typewriter fonts
 (added C<\hyphenchar\font=-1> to the C<\DeclareFontFamily> declarations).
-Added the I<-version> option, and renamed I<-verbose> to I<-Verbose>.
+Added the I<-version> option.
 
 =item I<2019-05-17>
 
@@ -2832,7 +3087,7 @@
 some FontFont fonts, where every font is in a family of its own.
 Added the "scaled" option (including the loading of F<xkeyval>)
 to the generated style file.
-Extended the output of the I<-Verbose> option.
+Extended the output of the I<-verbose> option.
 
 =item I<2007-02-08>
 
@@ -2910,7 +3165,7 @@
 file to include an interface for the ornaments and to load Lehman's NFSS
 extensions F<nfssext.sty> if this is installed; corrected the "fontname" codes
 for OT1, T1, LY1 and user-specific encodings; extended the output generated by
-the I<-Verbose> option; and rewrote and extended the documentation.
+the I<-verbose> option; and rewrote and extended the documentation.
 
 =item I<2005-06-16>
 

Modified: trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Build/source/texk/texlive/linked_scripts/fontools/ot2kpx	2019-06-26 20:41:25 UTC (rev 51473)
@@ -38,7 +38,7 @@
 use List::Util @List::Util::EXPORT_OK;
 use Pod::Usage;
 
-my $VERSION = "20190522";
+my $VERSION = "20190625";
 
 our ($NUM_GLYPHS, $UNITS_PER_EM, %kern);
 
@@ -48,12 +48,12 @@
     );
 
     Getopt::Long::GetOptions(
-        'help|?'    =>  sub { pod2usage(-verbose => 0); },
-        'version'   =>  sub { print "$VERSION\n"; exit; },
-        'doc'       =>  sub { pod2usage(-verbose => 2); },
-        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx; },
-        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx; },
-        'lua'       =>  sub { $ARGV{print_func} = \&print_lua; },
+        'help|?'    =>  sub { pod2usage(-verbose => 0) },
+        'version'   =>  sub { print "$VERSION\n"; exit },
+        'doc'       =>  sub { pod2usage(-verbose => 2) },
+        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx },
+        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx },
+        'lua'       =>  sub { $ARGV{print_func} = \&print_lua },
     ) or pod2usage(-verbose => 0);
     pod2usage(-verbose => 0) if @ARGV != 1;
 
@@ -100,8 +100,8 @@
 # Print kerning data in Adobe's KPX format
 # ------------------------------------------------------------------------
 sub print_kpx {
-    my %kern = %{ shift @_; };
-    my @glyph = @{ shift @_; };
+    my %kern = %{ shift @_ };
+    my @glyph = @{ shift @_ };
 
     my $num_kernpairs = sum map { scalar keys %{$kern{$_}} } keys %kern;
     print "StartKernData\nStartKernPairs $num_kernpairs\n";
@@ -119,8 +119,8 @@
 # Print kerning data as a Luatex custom font feature
 # ------------------------------------------------------------------------
 sub print_lua {
-    my %kern = %{ shift @_; };
-    my @glyph = @{ shift @_; };
+    my %kern = %{ shift @_ };
+    my @glyph = @{ shift @_ };
 
     print <<'END_FEATURE_PREFIX';
 fonts.handlers.otf.addfeature {
@@ -739,7 +739,7 @@
 
 =head1 SYNOPSIS
 
-B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<fontfile>
+B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<< <fontfile> >>
 
 
 =head1 DESCRIPTION
@@ -771,7 +771,7 @@
 Output the kerning data as a Luatex custom font feature,
 to be included in a C<\directlua> command.
 
-=item B<fontfile>
+=item B<< <fontfile> >>
 
 The OpenType font (both F<otf> and F<ttf> format are supported).
 
@@ -858,7 +858,7 @@
 
 =head1 VERSION
 
-This document describes B<ot2kpx> version 20190522.
+This document describes B<ot2kpx> version 20190625.
 
 
 =head1 RECENT CHANGES

Modified: trunk/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Build/source/texk/texlive/linked_scripts/tlshell/tlshell.tcl	2019-06-26 20:41:25 UTC (rev 51473)
@@ -130,6 +130,11 @@
   set ::default_bg white
 }
 
+# NOTE
+# text widgets aren't ttk widgets:
+# state disabled  => configure -state disabled
+# state !disabled => configure -state normal
+
 # dialog with textbox
 proc long_message {str type {p "."}} {
   # alternate messagebox implemented as custom dialog
@@ -252,18 +257,15 @@
     set ::busy [__ "Running"]
     . configure -menu .mn_empty
     foreach c [winfo children .] {
-      if {$c ne ".showlogs" && [winfo class $c] in \
-              [list TButton TCheckbutton TRadiobutton TEntry Treeview]} {
+      if {$c ne ".showlogs" && [winfo class $c] in $::active_cls} {
         # this should cover all relevant widgets in the main window
         $c state disabled
       }
     }
-    set ::busy [__ "Running"]
   } else { ; # enable
     . configure -menu .mn
     foreach c [winfo children .] {
-      if {[winfo class $c] in \
-              [list TButton TCheckbutton TRadiobutton TEntry Treeview]} {
+      if {[winfo class $c] in $::active_cls} {
         $c state !disabled
       }
     }
@@ -284,7 +286,8 @@
 array unset ::repos
 
 # mirrors: dict of dicts of lists of urls per country per continent
-set ::mirrors [dict create]
+# moved to tltcl.tcl
+#set ::mirrors [dict create]
 
 # dict of (local and global) package dicts
 set ::pkgs [dict create]
@@ -334,9 +337,12 @@
   }
 } ; # read_err_tempfile
 
-proc err_exit {} {
+proc err_exit {{m ""}} {
   do_debug "error exit"
-  read_err_tempfile
+  if [info exists ::err] read_err_tempfile
+  if {$m ne ""} {
+    set ::err_log [linsert $::err_log 0 $m]
+  }
   any_message [join $::err_log "\n"] "ok"
   exit
 } ; # err_exit
@@ -350,9 +356,8 @@
   # to process initial tlmgr output before continuing.
   unset -nocomplain ::done_waiting
   do_debug "opening tlmgr"
-  if [catch \
-          {open "|tlmgr $args --machine-readable shell 2>>$::err_file" w+} \
-          ::tlshl] {
+  set cmd [list "|tlmgr" {*}$args "--machine-readable" "shell" 2>>$::err_file]
+  if [catch {open $cmd w+} ::tlshl] {
     tk_messageBox -message [get_stacktrace]
     exit
   }
@@ -374,9 +379,10 @@
   # if it wants to wait for the command to finish
   set l "" ; # will contain the line to be read
   if {([catch {chan gets $::tlshl l} len] || [chan eof $::tlshl])} {
+    # copy as much of stderr as possible to ::err_log
+    catch {read_err_tempfile ; chan close $::err}
     if [chan eof $::tlshl] {
       catch {chan close $::tlshl}
-      catch {chan close $:err}
       unset -nocomplain ::tlshl
       unset -nocomplain ::err
       set ::perlpid 0
@@ -433,8 +439,8 @@
 
 proc log_widget_init {} {
   show_logs ; # create the logs dialog
-  .tllg.status configure -text [__ "Running"]
-  .tllg.close configure -state disabled
+  set ::busy [__ "Running"]
+  .tllg.close state disabled
 }
 
 proc log_widget_add l {
@@ -453,8 +459,8 @@
   if {$::tcl_platform(os) ne "Darwin"} {
     .tllg.log.tx configure -state disabled
   }
-  .tllg.status configure -text [__ "Idle"]
-  .tllg.close configure -state !disabled
+  set ::busy [__ "Idle"]
+  .tllg.close state !disabled
   bind .tllg <Escape> {.tllg.close invoke}
 }
 
@@ -470,10 +476,13 @@
   if $show {
     show_logs
     .tllg.status configure -text [__ "Running"]
-    .tllg.close configure -state disabled
+    .tllg.close state disabled
   }
   set l [llength $cmds]
   for {set i 0} {$i<$l} {incr i} {
+    if {! [info exists ::tlshl]} {
+      err_exit "Back end gone. Last command: \n  $::last_cmd"
+    }
     set cmd [lindex $cmds $i]
     set ::last_cmd $cmd
     unset -nocomplain ::done_waiting
@@ -519,9 +528,10 @@
 
 # The repositories play a small part in this front end. Tlmgr mostly works
 # with a virtual repository, which is the combined set of repositories,
-# with pinning applied. But get_packages_info_remote must invoke
+# with pinning applied if there is more than one repository.
+# But get_packages_info_remote must invoke
 # show_repositories to display updated verification info.
-# This proc is also invoked by initialize.
+# show_repositories is also invoked by initialize.
 
 # get_packages_info_local is invoked only once, at initialization.  After
 # installations and removals, the collected information is updated by
@@ -528,18 +538,18 @@
 # update_local_revnumbers.
 # Both procs also invoke get_platforms
 
-# get_packages_info_remote will be invoked by collect_filtered if
-# ::have_remote is false. Afterwards, ::have_remote will be true, and
-# therefore get_packages_info_remote will not be called again.
-# get_packages_info_remot also invokes get_platforms
-# get_packages_info_remote invokes update_globals and show_repos.
+# get_packages_info_remote should be invoked before collect_filtered if
+# ::have_remote is false. Afterwards, ::have_remote will be true.
+# There will be no need to invoke get_packages_info_remote again except
+# at a change of repository by repos_commit.
+# get_packages_info_remote invokes update_globals, show_repos
+# and get_platforms.
 
 # update_local_revnumbers will be invoked after any updates. It also
 # invokes update_globals.
 
 # collect_filtered does not only filter, but also organize the
-# information to be displayed.  If necessary, it invokes
-# get_packages_info_remote and always invokes display_packages_info.
+# information to be displayed. It invokes display_packages_info.
 # It is invoked at initialization, when filtering options change and
 # at the end of install-, remove- and update procs.
 
@@ -614,8 +624,9 @@
 proc collect_filtered {} {
   do_debug \
       "collect_filtered for $::stat_opt and $::dtl_opt"
+  # test this beforehand
   if {$::stat_opt ne "inst" && ! $::have_remote} {
-    get_packages_info_remote
+    err_exit "collect_filtered should not have been invoked at this time"
   }
   foreach nm [dict keys $::filtered] {
     dict unset ::filtered $nm
@@ -717,6 +728,57 @@
   get_platforms
 } ; # get_packages_info_local
 
+proc abort_load {} {
+  # try to close back end forcibly
+  catch {chan close $::tlshl}
+  if {$::tcl_platform(platform) eq "windows"} {
+    catch {exec -ignorestderr taskkill /pid $::perlpid /t /f}
+  } else {
+    catch {exec -ignorestderr kill -9 $::perlpid}
+    # should also be ok for darwin
+  }
+  # start new tlshell process
+  exec $::progname &
+
+  # end current tlshell process nicely
+  exit
+  # kill current tlshell process forcibly if necessary
+  if {$::tcl_platform(platform) eq "windows"} {
+    catch {exec -ignorestderr taskkill /pid [pid] /t /f}
+  } else {
+    catch {exec -ignorestderr kill -9 [pid]}
+    # kill -9 should also be ok for darwin
+  }
+} ; # abort load
+
+# activate abort button
+# toplevel with abort button in case loading of a repository takes too long.
+# it should disappear if loading finishes
+proc splash_loading {} {
+
+  #toplevel .loading
+  create_dlg .loading .
+
+  wm title .loading ""
+
+  # wallpaper
+  pack [ttk::frame .loading.bg -padding 3] -fill both -expand 1
+
+  set lbl [__ "Trying to load %s.
+
+If this takes too long, press Abort and choose another repository." \
+              $::repos(main)]
+  append lbl "\n([__ "Options"] \/ [__ "Repositories"] ...)"
+  ppack [ttk::label .loading.l0 -text $lbl \
+             -wraplength [expr {60*$::cw}] -justify left] \
+      -in .loading.bg -anchor w
+  pack [ttk::frame .loading.buttons] -in .loading.bg -expand 1 -fill x
+  ttk::button .loading.y -text [__ "Abort"] -command abort_load
+  ppack .loading.y -in .loading.buttons -side right
+  wm resizable .loading 0 0
+  place_dlg .loading .
+} ; # splash_loading
+
 # remote: preserve information on installed packages
 proc get_packages_info_remote {} {
   # remove non-local database entries
@@ -729,12 +791,15 @@
   set ::updatable 0
   set ::tlshell_updatable 0
 
-  if [catch {run_cmd_waiting \
+  splash_loading
+  if [catch {run_cmd \
     "info --data name,localrev,remoterev,cat-version,category,shortdesc"}] {
     do_debug [get_stacktrace]
     tk_messageBox -message [__ "A configured repository is unavailable."]
     return 0
   }
+  vwait ::done_waiting
+  destroy .loading
   set re {^([^,]+),([0-9]+),([0-9]+),([^,]*),([^,]*),(.*)$}
   foreach l $::out_log {
     if [regexp $re $l m nm lrev rrev rcatv catg pdescr] {
@@ -804,7 +869,8 @@
   pack [ttk::frame .tllg.bottom] -in .tllg.bg -side bottom -fill x
   ttk::button .tllg.close -text [__ "Close"] -command {end_dlg 0 .tllg}
   ppack .tllg.close -in .tllg.bottom -side right -anchor e
-  ppack [ttk::label .tllg.status -anchor w] -in .tllg.bottom -side left
+  ppack [ttk::label .tllg.status -textvariable ::busy -anchor w] \
+      -in .tllg.bottom -side left
   bind .tllg <Escape> {.tllg.close invoke}
   wm protocol .tllg WM_DELETE_WINDOW {.tllg.close invoke}
 
@@ -871,123 +937,21 @@
 ##### repositories ###############################################
 
 ### mirrors
+#mangle_name {n} {} ; moved to tltcl.tcl
+#proc read_mirrors {} {} ; moved to tltcl.tcl
 
-# turn name into a string suitable for a widget name
-proc mangle_name {n} {
-  set n [string tolower $n]
-  set n [string map {" "  "_"} $n]
-  return $n
-} ; # mangle_name
-
-set mirrors [dict create]
-proc read_mirrors {} {
-  if [catch {open [file join [exec kpsewhich -var-value SELFAUTOPARENT] \
-                   "tlpkg/installer/ctan-mirrors.pl"] r} fm] {
-    do_debug "cannot open mirror list"
-    return 0
-  }
-  set re_geo {^\s*'([^']+)' => \{\s*$}
-  set re_url {^\s*'(.*)' => ([0-9]+)}
-  set re_clo {^\s*\},?\s*$}
-  set starting 1
-  set lnum 0 ; # line number for error messages
-  set ok 1 ; # no errors encountered yet
-  set countries {} ; # aggregate list of countries
-  set urls {} ; # aggregate list of urls
-  set continent ""
-  set country ""
-  set u ""
-  set in_cont 0
-  set in_coun 0
-  while {! [catch {chan gets $fm} line] && ! [chan eof $fm]} {
-    incr lnum
-    if $starting {
-      if {[string first "\$mirrors =" $line] == 0} {
-        set starting 0
-        continue
-      } else {
-        set ok 0
-        set msg "Unexpected line '$line' at start"
-        break
-      }
-    }
-    # starting is now dealt with.
-    if [regexp $re_geo $line dummy c] {
-      if {! $in_cont} {
-        set in_cont 1
-        set continent $c
-        set cont_dict [dict create]
-        if {$continent in [dict keys $::mirrors]} {
-          set ok 0
-          set msg "Duplicate continent $c at line $lnum"
-          break
-        }
-      } elseif {! $in_coun} {
-        set in_coun 1
-        set country $c
-        if {$country in $countries} {
-          set ok 0
-          set msg "Duplicate country $c at line $lnum"
-          break
-        }
-        lappend countries $country
-        dict set cont_dict $country {}
-      } else {
-        set ok 0
-        set msg "Unexpected continent- or country line $line at line $lnum"
-        break
-      }
-    } elseif [regexp $re_url $line dummy u n] {
-      if {! $in_coun} {
-        set ok 0
-        set msg "Unexpected url line $line at line $lnum"
-        break
-      } elseif {$n ne "1"} {
-        continue
-      }
-      append u "systems/texlive/tlnet"
-      if {$u in $urls} {
-          set ok 0
-          set msg "Duplicate url $u at line $lnum"
-          break
-      }
-      dict lappend cont_dict $country $u
-      lappend urls $u
-      set u ""
-    } elseif [regexp $re_clo $line] {
-      if $in_coun {
-        set in_coun 0
-        set country ""
-      } elseif $in_cont {
-        set in_cont 0
-        dict set ::mirrors $continent $cont_dict
-        set continent ""
-      } else {
-        break ; # should close mirror list
-      }
-    } ; # ignore other lines
-  }
-  close $fm
-  if {! $ok} {do_debug $msg}
-} ; # read_mirrors
-
 proc pick_local_repo {} {
-  set tail "tlpkg/texlive.tlpdb"
   set nw_repo [.tlr.cur cget -text]
-  if {! [file exists [file join $nw_repo $tail]]} {
-    # not local, try originally configured main repository
-    set nw_repo $::repos(main)
-    if {! [file exists [file join $nw_repo $tail]]} {
-      # again, not local
-      set nw_repo $::env(HOME) ; # HOME also o.k. for windows
-    }
+  if {! [file isdirectory $nw_repo]} {
+    set nw_repo $::env(HOME) ; # HOME also o.k. for windows
   }
   while 1 {
     set nw_repo [browse4dir $nw_repo .tlr]
-    if {$nw_repo ne "" && ! [file exists [file join $nw_repo $tail]]} {
+    if {$nw_repo ne "" && ! [possible_repository $nw_repo]} {
       tk_messageBox -message [__ "%s not a repository" $nw_repo] -parent .tlr
       continue
     } else {
+      .tlr.save state !disabled
       break
     }
   }
@@ -998,7 +962,6 @@
 } ; # pick_local_repo
 
 proc get_repos_from_tlmgr {} {
-  #puts stderr "get_repos start"
   array unset ::repos
   run_cmd_waiting "option repository"
   set rps ""
@@ -1026,7 +989,6 @@
       array unset ::repos
     }
   }
-  #puts stderr "get_repos end"
 }; # get_repos_from_tlmgr
 
 proc set_repos_in_tlmgr {} {
@@ -1034,7 +996,6 @@
   # we need to compose a string for opt_location ourselves from $::repos.
   # a single repository should not get a tag.
   # apparently, we can safely ignore bogus pinning data.
-  #puts stderr "set_repos start"
   set nr [array size ::repos]
   set opt_repos ""
   set rp ""
@@ -1043,8 +1004,7 @@
       if {$nm ne "main"} {
         err_exit "Internal error"
       } else {
-        # pinning only supported for multiple repositories
-        run_cmd_waiting "pinning remove $nm --all"
+        # pinning command only supported for multiple repositories
         set rp $::repos(main)
       }
     } else {
@@ -1061,12 +1021,9 @@
     append opt_repos " $rp"
   }
   run_cmd_waiting "repository set [string range $opt_repos 1 end]"
-  #puts stderr [string range $opt_repos 1 end]
-  #puts stderr "set_repos end"
 }; # set_repos_in_tlmgr
 
 proc show_repos {} {
-  #puts stderr "show_repos start"
   set w .toprepo
   foreach ch [winfo children $w] {destroy $ch}
   set nms [array names ::repos]
@@ -1085,19 +1042,13 @@
     pgrid [ttk::label $w.load -text [__ "Not loaded"]] \
         -sticky nw -row 0 -column 1
   }
-  set do_veri 0
-  if {$::have_remote && [dict get $::pkgs texlive.infra localrev] >= 51140} {
-    set do_veri 1
-  }
   set repodict [dict create]
-  if $do_veri {
+  if $::have_remote {
     run_cmd_waiting "repository status"
     set re {^(\S+) (\S+)/tlpkg/texlive.tlpdb (-?\d+) (.*)$}
     foreach l $::out_log {
-      #puts stderr $l
       if [regexp $re $l dum nm rp n d] {
         # dummy tag repository verification_code description
-        #puts stderr "scanning..."
         # restore spaces and percent characters in nm and rp
         set nm [string map {"%20" " "} $nm]
         set nm [string map {"%25" "%"} $nm]
@@ -1106,11 +1057,8 @@
         dict set repodict $nm "url" $rp
         dict set repodict $nm "vericode" $n
         dict set repodict $nm "veridescr" $d
-        #puts stderr "${nm}: $rp"
       }
     }
-  } else {
-    #puts stderr "No veri"
   }
   set rw 0
   foreach nm [array names ::repos] {
@@ -1117,7 +1065,7 @@
     incr rw
     pgrid [ttk::label $w.u$nm -text $::repos($nm) -justify left] \
         -sticky nw -row $rw -column 0
-    if {$::repos($nm) eq $::any_mirror && $do_veri} {
+    if {$::repos($nm) eq $::any_mirror && $::have_remote} {
       set s $::repos($nm)
       append s "\n[__ "Actual repository"]:\n"
       append s [dict get $repodict $nm "url"]
@@ -1127,17 +1075,15 @@
       pgrid [ttk::label $w.n$nm -text "($nm)"] \
         -sticky nw -row $rw -column 1
     }
-    if $do_veri {
+    if $::have_remote {
       pgrid [ttk::label $w.v$nm -text \
                 "verification: [dict get $repodict $nm "veridescr"]"] \
             -sticky nw -row $rw -column 2
     }
   }
-  #puts stderr "show_repos end"
 } ; # show_repos
 
 proc repos_commit {} {
-  #puts stderr "repos_commit start"
   set changes 0
   # set repositories then add pinning if appropriate
   if {! [regexp {^\s*$} [.tlr.new get]]} {
@@ -1150,7 +1096,6 @@
   set had_contrib 0
   if $::toggle_contrib {
     set changes 1
-    #puts stderr "handle tlcontrib"
     foreach nm [array names ::repos] {
       if {$::repos($nm) eq $::tlcontrib} {
         set had_contrib 1
@@ -1171,15 +1116,31 @@
     if {$::toggle_contrib && ! $had_contrib} {
       run_cmd_waiting "pinning add tlcontrib \"*\""
     }
-    # reload remote package information
-    set ::have_remote 0
-    get_packages_info_remote
-    collect_filtered
-    #puts stderr "done committing"
   }
-  #puts stderr "really done committing"
 } ; # repos_commit
 
+proc dis_enable_reposave {} {
+  if [possible_repository [.tlr.new get]] {
+    .tlr.save state !disabled
+  } else {
+    .tlr.save state disabled
+  }
+}
+
+proc save_load_repo {} {
+  repos_commit
+  end_dlg "" .tlr
+  # reload remote package information
+  set ::have_remote 0
+  get_packages_info_remote
+  collect_filtered
+}
+
+proc select_mir {m} {
+  .tlr.new delete 0 end; .tlr.new insert end $m
+  .tlr.save state !disabled
+}
+
 # main repository dialog
 proc repository_dialog {} {
 
@@ -1211,6 +1172,8 @@
       -in .tlr.info -row $row -column 0 -sticky w
   pgrid [ttk::entry .tlr.new] \
       -in .tlr.info -row $row -column 1 -columnspan 2 -sticky ew
+  .tlr.new insert 0 $::repos(main)
+  bind .tlr.new <KeyRelease> dis_enable_reposave
 
   ### three ways to specify a repository ###
   pack [ttk::frame .tlr.mirbuttons] -in .tlr.bg -fill x
@@ -1218,32 +1181,12 @@
   ttk::button .tlr.ctan -text [__ "Any CTAN mirror"] -command {
     .tlr.new delete 0 end
     .tlr.new insert end $::any_mirror
+    .tlr.save state !disabled
   }
   ppack .tlr.ctan -in .tlr.mirbuttons -side left -fill x
   # 2. specific repository: create a cascading dropdown menu of mirrors
-  destroy .tlr.mir.m
-  if {[dict size $::mirrors] == 0} read_mirrors
-  do_debug "[dict size $::mirrors] mirrors"
-  if {[dict size $::mirrors] > 0} {
-    ttk::menubutton .tlr.mir -text [__ "Specific mirror..."] \
-        -direction below -menu .tlr.mir.m
-    ppack .tlr.mir -in .tlr.mirbuttons -side left -fill x
-    menu .tlr.mir.m
-    dict for {cont d_cont} $::mirrors {
-      set c_ed [mangle_name $cont]
-      menu .tlr.mir.m.$c_ed
-      .tlr.mir.m add cascade -label $cont -menu .tlr.mir.m.$c_ed
-      dict for {cntr urls} $d_cont {
-        set n_ed [mangle_name $cntr]
-        menu .tlr.mir.m.$c_ed.$n_ed
-        .tlr.mir.m.$c_ed add cascade -label $cntr -menu .tlr.mir.m.$c_ed.$n_ed
-        foreach u $urls {
-          .tlr.mir.m.$c_ed.$n_ed add command -label $u \
-              -command ".tlr.new delete 0 end; .tlr.new insert end $u"
-        }
-      }
-    }
-  }
+  mirror_menu .tlr.mir select_mir
+  ppack .tlr.mir -in .tlr.mirbuttons -side left -fill x
   # 3. local repository
   ttk::button .tlr.browse -text [__ "Local directory..."] -command {
     .tlr.new delete 0 end; .tlr.new insert end [pick_local_repo]}
@@ -1275,18 +1218,14 @@
 
   # two ways to close the dialog
   pack [ttk::frame .tlr.closebuttons] -pady [list 10 0] -in .tlr.bg -fill x
-  ttk::button .tlr.save -text [__ "Save and Load"] -command {
-    #puts stderr "save and load invoked"
-    repos_commit
-    end_dlg "" .tlr
-    #puts stderr "save and load done"
-  }
+  ttk::button .tlr.save -text [__ "Save and Load"] -command save_load_repo
   ppack .tlr.save -in .tlr.closebuttons -side right
-  ttk::button .tlr.abort -text [__ "Abort"] -command {end_dlg "" .tlr}
-  ppack .tlr.abort -in .tlr.closebuttons -side right
-  bind .tlr <Escape> {.tlr.abort invoke}
+  dis_enable_reposave
+  ttk::button .tlr.cancel -text [__ "Cancel"] -command {end_dlg "" .tlr}
+  ppack .tlr.cancel -in .tlr.closebuttons -side right
+  bind .tlr <Escape> {.tlr.cancel invoke}
 
-  #wm protocol .tlr WM_DELETE_WINDOW {.tlr.abort invoke}
+  wm protocol .tlr WM_DELETE_WINDOW {.tlr.cancel invoke}
   wm resizable .tlr 1 0
   place_dlg .tlr .
 } ; # repository_dialog
@@ -1315,10 +1254,10 @@
     } else {
       .tlpl.pl set $pl "sup" "[mark_sym $m0] \u21d2 [mark_sym $m1]"
     }
-    .tlpl.do configure -state disabled
+    .tlpl.do state disabled
     dict for {p mrks} $::platforms {
       if {[dict get $mrks "fut"] ne [dict get $mrks "cur"]} {
-        .tlpl.do configure -state !disabled
+        .tlpl.do state !disabled
         break
       }
     }
@@ -1367,12 +1306,14 @@
     # buttons
     pack [ttk::frame .tlpl.but] -in .tlpl.bg -side bottom -fill x
     ttk::button .tlpl.do -text [__ "Apply and close"] -command {
-      platforms_commit; end_dlg "" .tlpl
+      disable_dlg .tlpl
+      platforms_commit
+      end_dlg "" .tlpl
     }
     ttk::button .tlpl.dont -text [__ "Close"] -command \
         {end_dlg "" .tlpl}
     ppack .tlpl.do -in .tlpl.but -side right
-    .tlpl.do configure -state disabled
+    #.tlpl.do state disabled
     ppack .tlpl.dont -in .tlpl.but -side right
     bind .tlpl <Escape> {.tlpl.dont invoke}
 
@@ -1421,8 +1362,8 @@
 proc enable_restore {y_n} {
   set st [expr {$y_n ? !disabled : disabled}]
   .tlbk.bklist state $st
-  .tlbk.all configure -state $st
-  .tlbk.done configure -state $st
+  .tlbk.all state $st
+  .tlbk.done state $st
 } ; # enable_restore
 
 proc finish_restore {} {
@@ -1993,9 +1934,12 @@
   set ::err_log {}
   lappend ::out_log $mess
   unset -nocomplain ::done_waiting
-  # dont understand why, on windows, start_tlmgr does not trigger
-  # a console window but this proc does
-  if [catch {open "|$cmd 2>&1" "r"} ::capt] {
+  # treat cmd as a list, possibly of one element
+  # using a list enables a direct invocation, bypassing a shell
+  set cmd0 [lindex $cmd 0]
+  set cmd [lreplace $cmd 0 0 "|$cmd0"]
+  set cmd [list {*}$cmd 2>@1]
+  if [catch {open $cmd r} ::capt] {
     tk_messageBox -message "Failure to launch $cmd"
   }
   chan configure $::capt -buffering line -blocking 0
@@ -2026,6 +1970,18 @@
 
 ##### main window #####
 
+proc try_loading_remote {} {
+  if {[possible_repository $::repos(main)]} {
+    get_packages_info_remote
+    collect_filtered
+  } else {
+    set mes [__ "%s is not a local or remote repository.
+Please configure a valid repository" $::repos(main)]
+    append mes "\n([__ "Options"] \/ [__ "Repositories"] ...)"
+    tk_messageBox -message $mes -title [__ "Error"] -type ok -icon error
+  }
+}
+
 proc populate_main {} {
 
   wm withdraw .
@@ -2063,18 +2019,19 @@
     }
   }
 
+  # inx: keeping count to record indices where needed,
+  # i.e. when an entry needs to be referenced.
+  # not all submenus need this.
+
   .mn add cascade -label [__ "File"] -menu .mn.file -underline 0
   menu .mn.file
-  .mn.file add command -label [__ "Load default repository"] \
-      -command {get_packages_info_remote; collect_filtered}
+  .mn.file add command -label [__ "Load repository"] \
+      -command try_loading_remote
   .mn.file add command -command {destroy .} -label [__ "Exit"] -underline 1
 
-  # inx: keeping count to record indices where needed,
-  # i.e. when an entry needs to be referenced.
-  # not all submenus need this.
-
   .mn add cascade -label [__ "Actions"] -menu .mn.act -underline 0
   menu .mn.act
+  set inx -1
   incr inx
   .mn.act add command -label [__ "Regenerate filename database"] -command \
       {run_external "mktexlsr" [__ "Regenerating filename database..."]}
@@ -2162,7 +2119,7 @@
   # subframe for repositories, to be filled by show_repos
   pack [ttk::frame .toprepo] -in .topfl -side top -anchor w
 
-  # various info
+  # various info, left frame
   pack [ttk::frame .topfll] -in .topfl -side top -anchor nw -pady [list 6 0]
   ttk::label .topfll.lluptodate -text [__ "TL Manager up to date?"] -anchor w
   pgrid .topfll.lluptodate -row 2 -column 0 -sticky w
@@ -2176,7 +2133,7 @@
       -wraplength [expr {60*$::cw}] -justify left -anchor w
   pgrid .topfll.lcmd -row 3 -column 1 -sticky w
 
-  # right frame
+  # various info, right frame
   ppack [ttk::frame .topfr] -in .topf -side right -anchor ne
   if {$::tcl_platform(platform) eq "windows"} {
     pack [ttk::label .topfr.ladmin] -side top -anchor e
@@ -2203,9 +2160,15 @@
   ttk::radiobutton .pkfilter.inst -text [__ "Installed"] -value inst \
       -variable ::stat_opt -command collect_filtered
   ttk::radiobutton .pkfilter.alls -text [__ "All"] -value all \
-      -variable ::stat_opt -command collect_filtered
+      -variable ::stat_opt -command {
+        if {! $::have_remote} get_packages_info_remote
+        collect_filtered
+      }
   ttk::radiobutton .pkfilter.upd -text [__ "Updatable"] -value upd \
-      -variable ::stat_opt -command collect_filtered
+      -variable ::stat_opt -command {
+        if {! $::have_remote} get_packages_info_remote
+        collect_filtered
+      }
   grid .pkfilter.lstat -column 0 -row 0 -sticky w -padx {3 50}
   pgrid .pkfilter.inst -column 0 -row 1 -sticky w
   pgrid .pkfilter.alls -column 0 -row 2 -sticky w

Modified: trunk/Master/texmf-dist/doc/man/man1/afm2afm.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/afm2afm.1	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/doc/man/man1/afm2afm.1	2019-06-26 20:41:25 UTC (rev 51473)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "AFM2AFM 1"
-.TH AFM2AFM 1 "2019-05-22" "fontools" "Marc Penninga"
+.TH AFM2AFM 1 "2019-06-25" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -146,10 +146,10 @@
 .IX Item "afm2afm"
 [\fB\-help\fR]
 [\fB\-version\fR]
-[\fB\-encoding\fR \fIencodingfile\fR]
-[\fB\-kpx\fR \fIkpxfile\fR]
-[\fB\-output\fR \fIoutputfile\fR]
-\&\fBafmfile\fR
+[\fB\-encoding\fR=\fI<encodingfile>\fR]
+[\fB\-kpx\fR=\fI<kpxfile>\fR]
+[\fB\-output\fR=\fI<outputfile>\fR]
+\&\fB<afmfile>\fR
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
 \&\fBafm2afm\fR re-encodes an \fIafm\fR file.
@@ -175,16 +175,16 @@
 .IP "\fB\-version\fR" 4
 .IX Item "-version"
 Print version number and exit
-.IP "\fB\-encoding\fR \fIencodingfile\fR" 4
-.IX Item "-encoding encodingfile"
-Re-encode to the enconding in \fIencodingfile\fR
-.IP "\fB\-kpx\fR \fIkpxfile\fR" 4
-.IX Item "-kpx kpxfile"
-Read additional kerning pairs from \fIkpxfile\fR and add these to the output.
+.IP "\fB\-encoding\fR=\fI<encodingfile>\fR" 4
+.IX Item "-encoding=<encodingfile>"
+Re-encode to the enconding in \fI<encodingfile>\fR
+.IP "\fB\-kpx\fR=\fI<kpxfile>\fR" 4
+.IX Item "-kpx=<kpxfile>"
+Read additional kerning pairs from \fI<kpxfile>\fR and add these to the output.
 This option cannot be used to override values from the input \fIafm\fR file,
 since \fBafm2afm\fR will write both old and new values to the output!
 .Sp
-The \fIkpxfile\fR should contain kerning data in standard \fIafm\fR format,
+The \fI<kpxfile>\fR should contain kerning data in standard \fIafm\fR format,
 i.e. for each kerning pair there should be a line
 .Sp
 .Vb 1
@@ -191,12 +191,12 @@
 \&    KPX <left_glyph> <right_glyph> <amount>
 .Ve
 .Sp
-All other lines in the \fIkpxfile\fR are ignored.
-.IP "\fB\-output\fR \fIoutputfile\fR" 4
-.IX Item "-output outputfile"
-Write the result to \fIoutputfile\fR instead of \f(CW\*(C`stdout\*(C'\fR.
-.IP "\fBafmfile\fR" 4
-.IX Item "afmfile"
+All other lines in the \fI<kpxfile>\fR are ignored.
+.IP "\fB\-output\fR=\fI<outputfile>\fR" 4
+.IX Item "-output=<outputfile>"
+Write the result to \fI<outputfile>\fR instead of \f(CW\*(C`stdout\*(C'\fR.
+.IP "\fB<afmfile>\fR" 4
+.IX Item "<afmfile>"
 The \fIafm\fR file to be re-encoded.
 .PP
 You may use either one or two dashes before options,
@@ -223,7 +223,7 @@
 See the \s-1GNU\s0 General Public License for more details.
 .SH "VERSION"
 .IX Header "VERSION"
-This document describes \fBafm2afm\fR version 20190522.
+This document describes \fBafm2afm\fR version 20190625.
 .SH "RECENT CHANGES"
 .IX Header "RECENT CHANGES"
 (See the source code for the rest of the story.)

Modified: trunk/Master/texmf-dist/doc/man/man1/afm2afm.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/man/man1/autoinst.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/autoinst.1	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/doc/man/man1/autoinst.1	2019-06-26 20:41:25 UTC (rev 51473)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "AUTOINST 1"
-.TH AUTOINST 1 "2019-05-22" "fontools" "Marc Penninga"
+.TH AUTOINST 1 "2019-06-25" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -158,8 +158,9 @@
 \&\fBautoinst\fR will create several LaTeX font families:
 .RS 2
 .IP "\-" 3
-Four text families (with lining and oldstyle digits, each in both tabular
-and proportional variants), all with the following shapes:
+Four text families (with lining and oldstyle digits,
+each in both tabular and proportional variants),
+all with the following shapes:
 .RS 3
 .RS 2
 .IP "\fIn\fR" 8
@@ -187,13 +188,14 @@
 .RS 3
 .RE
 .IP "\-" 3
-For each T1\-encoded text family: a family of TS1\-encoded symbol fonts,
-in roman, italic and slanted shapes.
+For each T1\-encoded text family:
+a family of TS1\-encoded symbol fonts, in roman, italic and slanted shapes.
 .IP "\-" 3
 Families with superiors, inferiors, numerators and denominators,
 in roman, italic and slanted shapes.
 .IP "\-" 3
-Families with \*(L"Titling\*(R" characters; these \*(L"... replace the default glyphs
+Families with \*(L"Titling\*(R" characters;
+these \*(L"... replace the default glyphs
 with corresponding forms designed specifically for titling.
 These may be all-capital and/or larger on the body,
 and adjusted for viewing at larger sizes\*(R"
@@ -258,14 +260,14 @@
 see the \fI\-logfile\fR command-line option in \*(L"COMMAND-LINE \s-1OPTIONS\*(R"\s0 below.
 If this log file already exists, \fBautoinst\fR will append its data to the end
 rather than overwrite it.
-Use the \fI\-Verbose\fR command-line option to ask for more detailed info.
+Use the \fI\-verbose\fR command-line option to ask for more detailed info.
 .SS "A note for MiKTeX users"
 .IX Subsection "A note for MiKTeX users"
 Automatically installing the fonts into a suitable \s-1TEXMF\s0 tree
-(as \fBautoinst\fR tries to do by default) only works for TeX-installations that use
-the \fIkpathsea\fR library; with TeX distributions that implement their
-own directory searching (such as MiKTeX), \fBautoinst\fR will complain that
-it cannot find the \fIkpsewhich\fR program and move all generated files
+(as \fBautoinst\fR tries to do by default) only works for TeX-installations
+that use the \fIkpathsea\fR library; with TeX distributions that implement
+their own directory searching (such as MiKTeX), \fBautoinst\fR will complain
+that it cannot find the \fIkpsewhich\fR program and move all generated files
 into a subdirectory \f(CW\*(C`./autoinst_output/\*(C'\fR of the current directory.
 If you use such a TeX distribution, you should either move these files
 to their correct destinations by hand, or use the \fI\-target\fR option
@@ -277,11 +279,11 @@
 and TeXLive (\fIhttp://tug.org/texlive\fR) don't seem to have this problem.
 .SS "A note for MacTeX users"
 .IX Subsection "A note for MacTeX users"
-By default, \fBautoinst\fR will try to install all files into the \f(CW$TEXMFLOCAL\fR tree;
-when this directory isn't user-writable, it will use the \f(CW$TEXMFHOME\fR tree instead.
-Unfortunately, MacTeX's version of \f(CW\*(C`updmap\-sys\*(C'\fR
-(which is called behind the scenes) doesn't search in \f(CW$TEXMFHOME\fR,
-and hence MacTeX will not find the new fonts.
+By default, \fBautoinst\fR will try to install all generated files into
+the \f(CW$TEXMFLOCAL\fR tree; when this directory isn't user-writable,
+it will use the \f(CW$TEXMFHOME\fR tree instead.  Unfortunately, MacTeX's version
+of \f(CW\*(C`updmap\-sys\*(C'\fR (which is called behind the scenes) doesn't search
+in \f(CW$TEXMFHOME\fR, and hence MacTeX will not find the new fonts.
 .PP
 To remedy this, either run \fBautoinst\fR as root (so that it can install
 everything into \f(CW$TEXMFLOCAL\fR) or manually run \f(CW\*(C`updmap \-user\*(C'\fR to tell
@@ -291,8 +293,8 @@
 .SS "Using the fonts in your LaTeX documents"
 .IX Subsection "Using the fonts in your LaTeX documents"
 \&\fBautoinst\fR generates a style file for using the fonts in LaTeX documents,
-named \fI<FontFamily>.sty\fR. This style file also takes care of loading the
-\&\fIfontenc\fR and \fItextcomp\fR packages.
+named \fI<FontFamily>.sty\fR. This style file also takes care of loading
+the \fIfontenc\fR and \fItextcomp\fR packages.
 To use the fonts, add the command \f(CW\*(C`\eusepackage{\f(CI<FontFamily>\f(CW}\*(C'\fR
 to the preamble of your document.
 .PP
@@ -335,7 +337,7 @@
 you have the \fImweights\fR package installed.
 .PP
 The style file will also try to load the \fIfontaxes\fR package
-(available on \s-1CTAN\s0), which gives easy access to various font shapes and styles.
+(on \s-1CTAN\s0), which gives easy access to various font shapes and styles.
 Using the machinery set up by \fIfontaxes\fR, the generated style file
 defines a number of commands (which take the text to be typeset as argument)
 and declarations (which don't take arguments, but affect all text up to
@@ -351,8 +353,8 @@
 .Ve
 .PP
 In addition, the \f(CW\*(C`\eswshape\*(C'\fR and \f(CW\*(C`\etextsw\*(C'\fR commands are redefined to place
-swash on \fIfontaxes\fR' secondary shape axis (\fIfontaxes\fR places it on the primary
-shape axis) to make them behave properly when nested, so that
+swash on \fIfontaxes\fR' secondary shape axis (\fIfontaxes\fR places it on the
+primary shape axis) to make them behave properly when nested, so that
 \&\f(CW\*(C`\eswshape\eupshape\*(C'\fR will give upright swash.
 .PP
 There are no commands for accessing the numerator and denominator
@@ -369,8 +371,8 @@
 To access ornament glyphs, \fBautoinst\fR creates a font-specific encoding file
 \&\fI<FontFamily>_orn.enc\fR,
 but only if that file doesn't yet exist in the current directory.
-This is a deliberate feature that allows you to provide your own
-encoding vector, e.g. if your fonts use non-standard glyph names for ornaments.
+This is a deliberate feature that allows you to provide your own encoding
+vector, e.g. if your fonts use non-standard glyph names for ornaments.
 .PP
 These commands are only generated for existing shapes and number styles;
 no commands are generated for shapes and styles that don't exist,
@@ -434,7 +436,7 @@
 Of course, not all 81 combinations of these \s-1NFSS\s0 weights and widths will map
 to existing fonts;
 and conversely it may not be possible to assign every existing font
-a unique code in a sane way (especially on the weight axis, some font families
+a unique code in a sane way (especially for the weights, some font families
 offer more choices or finer granularity than \s-1NFSS\s0's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional \*(L"Medium\*(R" weight between Regular and Semibold).
@@ -477,8 +479,8 @@
 Write log data to \fIfilename\fR instead of the default \fI<fontfamily>.log\fR.
 If the file already exists, \fBautoinst\fR appends to it;
 it doesn't overwrite an existing file.
-.IP "\fB\-Verbose\fR (\fInote:\fR uppercase 'V'!)" 4
-.IX Item "-Verbose (note: uppercase 'V'!)"
+.IP "\fB\-verbose\fR" 4
+.IX Item "-verbose"
 Add more details to the log file. Repeat this option for even more info.
 .IP "\fB\-encoding\fR=\fIencoding[,encoding]\fR" 4
 .IX Item "-encoding=encoding[,encoding]"
@@ -491,16 +493,16 @@
 The default choice of encodings is \*(L"\s-1OT1,T1,LY1\*(R".\s0
 For each encoding, a file \fI<encoding>.enc\fR (in all \fIlowercase\fR!)
 should be somewhere where \fIotftotfm\fR can find it. Suitable encoding files
-for \s-1OT1, T1/TS1, LY1, LGR\s0 and T2A/B/C come with \fBautoinst\fR. (These files are
-called \fIfontools_ot1.enc\fR etc. to avoid name clashes with other packages;
-the \*(L"fontools_\*(R" prefix may be omitted.)
-.IP "\fB\-ts1\fR / \fB\-nots1\fR" 4
-.IX Item "-ts1 / -nots1"
+for \s-1OT1, T1/TS1, LY1, LGR, T2A/B/C\s0 and T3/TS3 come with \fBautoinst\fR.
+(These files are called \fIfontools_ot1.enc\fR etc. to avoid name clashes
+with other packages; the \*(L"fontools_\*(R" prefix may be omitted.)
+.IP "\fB\-ts1\fR/\fB\-nots1\fR" 4
+.IX Item "-ts1/-nots1"
 Control the creation of TS1\-encoded fonts. The default is \fB\-ts1\fR
 if the text encodings (see \fI\-encoding\fR above) include T1,
 \&\fB\-nots1\fR otherwise.
-.IP "\fB\-serif\fR / \fB\-sanserif\fR / \fB\-typewriter\fR" 4
-.IX Item "-serif / -sanserif / -typewriter"
+.IP "\fB\-serif\fR/\fB\-sanserif\fR/\fB\-typewriter\fR" 4
+.IX Item "-serif/-sanserif/-typewriter"
 Install the font as a serif, sanserif or typewriter font, respectively.
 This changes how you access the font in LaTeX:
 with \f(CW\*(C`\ermfamily\*(C'\fR/\f(CW\*(C`\etextrm\*(C'\fR, \f(CW\*(C`\esffamily\*(C'\fR/\f(CW\*(C`\etextsf\*(C'\fR
@@ -512,38 +514,49 @@
 and it will disable hyphenation for this font.
 This latter effect cannot be disabled in \fBautoinst\fR;
 if you want typewriter text to be hyphenated, use the \fIhyphenat\fR package.
-.IP "\fB\-lining\fR / \fB\-nolining\fR" 4
-.IX Item "-lining / -nolining"
+.Sp
+If none of these options is specified, \fBautoinst\fR tries to guess:
+if the font's filename contains the string \*(L"mono\*(R"
+or if the field \f(CW\*(C`isFixedPitch\*(C'\fR in the font's \fIpost\fR table is True,
+it will select \fB\-typewriter\fR;
+else if the filename contains \*(L"sans\*(R" it selects \fB\-sanserif\fR;
+and otherwise it will opt for \fB\-serif\fR.
+.IP "\fB\-lining\fR/\fB\-nolining\fR" 4
+.IX Item "-lining/-nolining"
 Control the creation of fonts with lining figures. The default is
 \&\fB\-lining\fR.
-.IP "\fB\-oldstyle\fR / \fB\-nooldstyle\fR" 4
-.IX Item "-oldstyle / -nooldstyle"
+.IP "\fB\-oldstyle\fR/\fB\-nooldstyle\fR" 4
+.IX Item "-oldstyle/-nooldstyle"
 Control the creation of fonts with oldstyle figures. The default is
 \&\fB\-oldstyle\fR.
-.IP "\fB\-proportional\fR / \fB\-noproportional\fR" 4
-.IX Item "-proportional / -noproportional"
+.IP "\fB\-proportional\fR/\fB\-noproportional\fR" 4
+.IX Item "-proportional/-noproportional"
 Control the creation of fonts with proportional figures. The default is
 \&\fB\-proportional\fR.
-.IP "\fB\-tabular\fR / \fB\-notabular\fR" 4
-.IX Item "-tabular / -notabular"
+.IP "\fB\-tabular\fR/\fB\-notabular\fR" 4
+.IX Item "-tabular/-notabular"
 Control the creation of fonts with tabular figures. The default is
 \&\fB\-tabular\fR.
-.IP "\fB\-smallcaps\fR / \fB\-nosmallcaps\fR" 4
-.IX Item "-smallcaps / -nosmallcaps"
+.IP "\fB\-smallcaps\fR/\fB\-nosmallcaps\fR" 4
+.IX Item "-smallcaps/-nosmallcaps"
 Control the creation of small caps fonts. The default is
 \&\fB\-smallcaps\fR.
-.IP "\fB\-swash\fR / \fB\-noswash\fR" 4
-.IX Item "-swash / -noswash"
+.IP "\fB\-swash\fR/\fB\-noswash\fR" 4
+.IX Item "-swash/-noswash"
 Control the creation of swash fonts. The default is \fB\-swash\fR.
-.IP "\fB\-titling\fR / \fB\-notitling\fR" 4
-.IX Item "-titling / -notitling"
+.IP "\fB\-titling\fR/\fB\-notitling\fR" 4
+.IX Item "-titling/-notitling"
 Control the creation of titling families. The default is \fB\-titling\fR.
-.IP "\fB\-superiors\fR / \fB\-nosuperiors\fR" 4
-.IX Item "-superiors / -nosuperiors"
+.IP "\fB\-superiors\fR/\fB\-nosuperiors\fR" 4
+.IX Item "-superiors/-nosuperiors"
 Control the creation of fonts with superior characters.
 The default is \fB\-superiors\fR.
-.IP "\fB\-inferiors\fR=[ \fBnone\fR | \fBauto\fR | \fBsubs\fR | \fBsinf\fR | \fBdnom\fR ]" 4
-.IX Item "-inferiors=[ none | auto | subs | sinf | dnom ]"
+.IP "\fB\-noinferiors\fR" 4
+.IX Item "-noinferiors"
+.PD 0
+.IP "\fB\-inferiors\fR [= \fBnone\fR | \fBauto\fR | \fBsubs\fR | \fBsinf\fR | \fBdnom\fR ]" 4
+.IX Item "-inferiors [= none | auto | subs | sinf | dnom ]"
+.PD
 The OpenType standard defines several kinds of digits that might be used
 as inferiors or subscripts: \*(L"Subscripts\*(R" (OpenType feature \*(L"subs\*(R"),
 \&\*(L"Scientific Inferiors\*(R" (\*(L"sinf\*(R"), and \*(L"Denominators\*(R" (\*(L"dnom\*(R").
@@ -551,30 +564,32 @@
 should use for the inferior characters.
 Alternatively, the value \*(L"auto\*(R" tells \fBautoinst\fR to use the first value
 in \*(L"subs\*(R", \*(L"sinf\*(R" or \*(L"dnom\*(R" that is supported by the font.
-The default value is \*(L"none\*(R".
+Saying just \fB\-inferiors\fR is equivalent to \fB\-inferiors=auto\fR;
+otherwise the default is \fB\-noinferiors\fR.
 .Sp
 \&\fIIf you specify a style of inferiors that isn't present in the font,
 \&\f(BIautoinst\fI will fall back to its default behaviour of not creating fonts
 with inferiors at all; it won't try to substitute one of the other styles.\fR
-.IP "\fB\-fractions\fR / \fB\-nofractions\fR" 4
-.IX Item "-fractions / -nofractions"
+.IP "\fB\-fractions\fR/\fB\-nofractions\fR" 4
+.IX Item "-fractions/-nofractions"
 Control the creation of fonts with numerators and denominators.
 The default is \fB\-nofractions\fR.
-.IP "\fB\-ligatures\fR / \fB\-noligatures\fR" 4
-.IX Item "-ligatures / -noligatures"
+.IP "\fB\-ligatures\fR/\fB\-noligatures\fR" 4
+.IX Item "-ligatures/-noligatures"
 Some fonts create glyphs for the standard f\-ligatures (ff, fi, fl, ffi, ffl),
 but don't provide a \*(L"liga\*(R" feature to access these.
 This option tells \fBautoinst\fR to add extra \f(CW\*(C`LIGKERN\*(C'\fR rules to
 the generated fonts to enable the use of these ligatures.
-The default is \fB\-ligatures\fR, unless the user specified the \fIligatures\fR option.
+The default is \fB\-ligatures\fR,
+unless the user specified the \fIligatures\fR option.
 .Sp
 Specify \fB\-noligatures\fR to disable the generation of ligatures even for fonts
 that do contain a \*(L"liga\*(R" feature.
-.IP "\fB\-defaultlining\fR / \fB\-defaultoldstyle\fR" 4
-.IX Item "-defaultlining / -defaultoldstyle"
+.IP "\fB\-defaultlining\fR/\fB\-defaultoldstyle\fR" 4
+.IX Item "-defaultlining/-defaultoldstyle"
 .PD 0
-.IP "\fB\-defaulttabular\fR / \fB\-defaultproportional\fR" 4
-.IX Item "-defaulttabular / -defaultproportional"
+.IP "\fB\-defaulttabular\fR/\fB\-defaultproportional\fR" 4
+.IX Item "-defaulttabular/-defaultproportional"
 .PD
 Tell \fBautoinst\fR which figure style is the current font family's default
 (i.e., which figures you get when you don't specify any OpenType features).
@@ -593,20 +608,16 @@
 to the commands for \fIotftotfm\fR to suppress such kerns.
 Note that this option leads to very long commands (it adds
 one hundred \fI \-\-ligkern\fR options), which may cause problems on some systems.
-.IP "\fB\-mergewidths\fR / \fB\-nomergewidths\fR" 4
-.IX Item "-mergewidths / -nomergewidths"
-Some font families put their Condensed, Narrow, Extended etc. widths
-in separate families;
-this option tells \fBautoinst\fR to merge those separate families into
+.IP "\fB\-mergewidths\fR/\fB\-nomergewidths\fR, \fB\-mergeweights\fR/\fB\-nomergeweights\fR, \fB\-mergeshapes\fR/\fB\-nomergeshapes\fR" 4
+.IX Item "-mergewidths/-nomergewidths, -mergeweights/-nomergeweights, -mergeshapes/-nomergeshapes"
+Some font put different widths, weights or shapes (e.g., small caps)
+in separate families.
+These options tell \fBautoinst\fR to merge those separate families into
 the main family.
-The default is \fB\-mergewidths\fR.
-.IP "\fB\-mergesmallcaps\fR / \fB\-nomergesmallcaps\fR" 4
-.IX Item "-mergesmallcaps / -nomergesmallcaps"
-Even more annoyingly, some font families put their small caps fonts
-in a separate family;
-this option tells \fBautoinst\fR to merge the small caps fonts into
-the main family.
-The default is \fB\-mergesmallcaps\fR.
+Since this is usually desirable, they are all enabled by default.
+.Sp
+In earlier versions, \fB\-mergeshapes\fR was called \fB\-mergesmallcaps\fR;
+for reasons of backward compatibility, that option is still supported.
 .IP "\fB\-nfssweight\fR=\fIcode\fR=\fIweight\fR, \fB\-nfsswidth\fR=\fIcode\fR=\fIwidth\fR" 4
 .IX Item "-nfssweight=code=weight, -nfsswidth=code=width"
 Map the \s-1NFSS\s0 code \fIcode\fR to the given weight or width,
@@ -613,18 +624,20 @@
 overriding the built-in tables.
 Each of these options may be given multiple times,
 to override more than one \s-1NFSS\s0 code.
-Example: to map the \*(L"ul\*(R" code to the \*(L"Thin\*(R" weight, use \f(CW\*(C`\-nfssweight=ul=thin\*(C'\fR.
-To inhibit the use of the \*(L"ul\*(R" code completely, use \f(CW\*(C`\-nfssweight=ul=\*(C'\fR.
+Example: to map the \*(L"ul\*(R" code to the \*(L"Thin\*(R" weight,
+use \f(CW\*(C`\-nfssweight=ul=thin\*(C'\fR.
+To inhibit the use of the \*(L"ul\*(R" code completely,
+use \f(CW\*(C`\-nfssweight=ul=\*(C'\fR.
 .IP "\fB\-extra\fR=\fItext\fR" 4
 .IX Item "-extra=text"
 Append \fItext\fR as extra options to the command lines for \fIotftotfm\fR.
-To prevent \fItext\fR from accidentily being interpreted as options to \fBautoinst\fR,
-it should be properly quoted.
+To prevent \fItext\fR from accidentily being interpreted as options
+to \fBautoinst\fR, it should be properly quoted.
 .IP "\fB\-manual\fR" 4
 .IX Item "-manual"
-Manual mode; for users who want to post-process the generated files and commands.
-By default, \fBautoinst\fR immediately executes all \fIotftotfm\fR commands
-it generates;
+Manual mode; for users who want to post-process the generated files
+and commands. By default, \fBautoinst\fR immediately executes all
+\&\fIotftotfm\fR commands it generates;
 in manual mode, these are instead written to a file \fIautoinst.bat\fR.
 Furthermore it tells \fIotftotfm\fR to generate human readable (and editable)
 \&\fIpl/vpl\fR files instead of the default \fItfm/vf\fR ones,
@@ -634,20 +647,20 @@
 When using this option, you need to execute the following manual steps after
 \&\fBautoinst\fR has finished:
 .RS 4
-.IP "\fB\-\fR run \fIpltotf\fR and \fIvptovf\fR on the generated \fIpl\fR and \fIvf\fR files, to convert them to \fItfm/vf\fR format;" 2
+.IP "\- run \fIpltotf\fR and \fIvptovf\fR on the generated \fIpl\fR and \fIvf\fR files, to convert them to \fItfm/vf\fR format;" 2
 .IX Item "- run pltotf and vptovf on the generated pl and vf files, to convert them to tfm/vf format;"
 .PD 0
-.IP "\fB\-\fR move all generated files to a proper \s-1TEXMF\s0 tree, and, if necessary, update the filename database;" 2
+.IP "\- move all generated files to a proper \s-1TEXMF\s0 tree, and, if necessary, update the filename database;" 2
 .IX Item "- move all generated files to a proper TEXMF tree, and, if necessary, update the filename database;"
-.ie n .IP "\fB\-\fR tell TeX about the new \fImap\fR file (usually by running ""updmap"" or similar)." 2
-.el .IP "\fB\-\fR tell TeX about the new \fImap\fR file (usually by running \f(CWupdmap\fR or similar)." 2
+.ie n .IP "\- tell TeX about the new \fImap\fR file (usually by running ""updmap"" or similar)." 2
+.el .IP "\- tell TeX about the new \fImap\fR file (usually by running \f(CWupdmap\fR or similar)." 2
 .IX Item "- tell TeX about the new map file (usually by running updmap or similar)."
 .RE
 .RS 4
 .PD
 .Sp
-Note that some options (\fI\-target\fR, \fI\-vendor\fR and \fI\-typeface\fR, \fI\-[no]updmap\fR)
-are meaningless, and hence ignored, in manual mode.
+Note that some options (\fI\-target\fR, \fI\-vendor\fR and \fI\-typeface\fR,
+\&\fI\-[no]updmap\fR) are meaningless, and hence ignored, in manual mode.
 .RE
 .IP "\fB\-target\fR=\fI\s-1DIRECTORY\s0\fR" 4
 .IX Item "-target=DIRECTORY"
@@ -660,7 +673,8 @@
 it will print a warning message and put all files into the subdirectory
 \&\f(CW\*(C`./autoinst_output/\*(C'\fR of the current directory.
 It's then up to the user to move the generated files to a better location
-and update all relevant databases (usually by calling \fItexhash\fR and \fIupdmap\fR).
+and update all relevant databases
+(usually by calling \fItexhash\fR and \fIupdmap\fR).
 .IP "\fB\-vendor\fR=\fI\s-1VENDOR\s0\fR" 4
 .IX Item "-vendor=VENDOR"
 .PD 0
@@ -674,8 +688,8 @@
 .Sp
 Note that these options change \fIonly\fR directory names,
 not the names of any generated files.
-.IP "\fB\-updmap\fR / \fB\-noupdmap\fR" 4
-.IX Item "-updmap / -noupdmap"
+.IP "\fB\-updmap\fR/\fB\-noupdmap\fR" 4
+.IX Item "-updmap/-noupdmap"
 Control whether or not \fIupdmap\fR is called after the last call to \fIotftotfm\fR.
 The default is \fB\-updmap\fR.
 .SH "SEE ALSO"
@@ -687,20 +701,21 @@
 For Windows, try ActivePerl (\fIhttp://www.activestate.com\fR)
 or Strawberry Perl (\fIhttp://strawberryperl.com\fR).
 .PP
-\&\fBXeTeX\fR (\fIhttp://www.tug.org/xetex\fR) and \fBLuaTeX\fR (\fIhttp://www.luatex.org\fR)
+\&\fBXeTeX\fR (\fIhttp://www.tug.org/xetex\fR) and
+\&\fBLuaTeX\fR (\fIhttp://www.luatex.org\fR)
 are Unicode-aware TeX engines that can use OpenType fonts directly,
 without any (La)TeX\-specific support files.
 .PP
 The \fBFontPro\fR project (\fIhttps://github.com/sebschub/FontPro\fR)
-offers very complete LaTeX support (even for typesetting maths) for Adobe's
-Minion Pro, Myriad Pro and Cronos Pro font families.
+offers very complete LaTeX support (even for typesetting maths) for
+Adobe's Minion Pro, Myriad Pro and Cronos Pro font families.
 .SH "AUTHOR"
 .IX Header "AUTHOR"
 Marc Penninga (\fImarcpenninga at gmail.com\fR)
 .PP
-When sending a bug report, please give as much relevant information as possible;
-this usually includes (but may not be limited to) the log file
-(please add the \fI\-Verbose\fR command-line option, for extra info).
+When sending a bug report, please give as much relevant information as
+possible; this usually includes (but may not be limited to) the log file
+(please add the \fI\-verbose\fR command-line option, for extra info).
 If you see any error messages, please include these \fIverbatim\fR;
 don't paraphase.
 .SH "COPYRIGHT"
@@ -722,16 +737,46 @@
 \&\s-1GNU\s0 General Public License for more details.
 .SH "VERSION"
 .IX Header "VERSION"
-This document describes \fBautoinst\fR version 20190522.
+This document describes \fBautoinst\fR version 20190625.
 .SH "RECENT CHANGES"
 .IX Header "RECENT CHANGES"
 (See the source for the full story, all the way back to 2005.)
+.IP "\fI2019\-06\-25\fR" 12
+.IX Item "2019-06-25"
+.RS 12
+.PD 0
+.IP "\-" 3
+.PD
+Added the \fI\-mergeweights\fR and \fI\-mergeshapes\fR options,
+and improved \fI\-mergewidths\fR.
+.IP "\-" 3
+Improved the parsing of fonts' widths and weights.
+.IP "\-" 3
+Improved the mapping of widths and weights to \s-1NFSS\s0 codes.
+.IP "\-" 3
+Changed logging code so that that results of font info parsing
+are always logged, even (especially!) when parsing fails.
+.IP "\-" 3
+Added a warning when installing fonts from multiple families.
+.IP "\-" 3
+Added simple recognition for sanserif and typewriter fonts.
+.IP "\-" 3
+Fixed error checking after calls to \fIotfinfo\fR
+(\fBautoinst\fR previously only checked whether \f(CW\*(C`fork()\*(C'\fR was successful,
+not whether the actual call to \fIotfinfo\fR worked).
+.IP "\-" 3
+Fixed a bug in the \fI\-inferiors\fR option;
+when used without a (supposedly optional) value,
+it would silently gobble the next option instead.
+.RE
+.RS 12
+.RE
 .IP "\fI2019\-05\-22\fR" 12
 .IX Item "2019-05-22"
 Added the \fImainfont\fR option to the generated \fIsty\fR files.
 Prevented hyphenation for typewriter fonts
 (added \f(CW\*(C`\ehyphenchar\efont=\-1\*(C'\fR to the \f(CW\*(C`\eDeclareFontFamily\*(C'\fR declarations).
-Added the \fI\-version\fR option, and renamed \fI\-verbose\fR to \fI\-Verbose\fR.
+Added the \fI\-version\fR option.
 .IP "\fI2019\-05\-17\fR" 12
 .IX Item "2019-05-17"
 Changed the way the \fI\-ligatures\fR option works:

Modified: trunk/Master/texmf-dist/doc/man/man1/autoinst.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/doc/man/man1/ot2kpx.1	2019-06-26 20:41:25 UTC (rev 51473)
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "OT2KPX 1"
-.TH OT2KPX 1 "2019-05-22" "fontools" "Marc Penninga"
+.TH OT2KPX 1 "2019-06-25" "fontools" "Marc Penninga"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -142,7 +142,7 @@
 ot2kpx \- extract kerning information from OpenType fonts
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
-\&\fBot2kpx\fR [ \fI\-afm\fR | \fI\-kpx\fR | \fI\-lua\fR ] \fBfontfile\fR
+\&\fBot2kpx\fR [ \fI\-afm\fR | \fI\-kpx\fR | \fI\-lua\fR ] \fB<fontfile>\fR
 .SH "DESCRIPTION"
 .IX Header "DESCRIPTION"
 \&\fBot2kpx\fR extract the kerning data from OpenType fonts and prints it
@@ -164,8 +164,8 @@
 .IX Item "-lua"
 Output the kerning data as a Luatex custom font feature,
 to be included in a \f(CW\*(C`\edirectlua\*(C'\fR command.
-.IP "\fBfontfile\fR" 4
-.IX Item "fontfile"
+.IP "\fB<fontfile>\fR" 4
+.IX Item "<fontfile>"
 The OpenType font (both \fIotf\fR and \fIttf\fR format are supported).
 .SH "RESTRICTIONS"
 .IX Header "RESTRICTIONS"
@@ -228,7 +228,7 @@
 See the \s-1GNU\s0 General Public License for more details.
 .SH "VERSION"
 .IX Header "VERSION"
-This document describes \fBot2kpx\fR version 20190522.
+This document describes \fBot2kpx\fR version 20190625.
 .SH "RECENT CHANGES"
 .IX Header "RECENT CHANGES"
 (See the source code for the rest of the story.)

Modified: trunk/Master/texmf-dist/doc/man/man1/ot2kpx.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/fontools/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/fontools/README	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/doc/support/fontools/README	2019-06-26 20:41:25 UTC (rev 51473)
@@ -15,16 +15,19 @@
 
     AFM2AFM - re-encode .afm files
 
-    OT2KPX - extract kerning pairs from OpenType fonts.
+    OT2KPX - extract kerning pairs from OpenType fonts
 
+    SPLITTTC - split an OpenType Collection file (ttc or otc) into
+               individual fonts
 
 
+
 PREREQUISITES
 =============
 
 Perl
 
-    The Fontools are written in Perl; any version since v5.10.1 should work.
+    The Fontools are written in Perl; any remotely recent version should work.
     Perl is usually installed on Linux and Unix systems;
     for Windows, try ActivePerl (http://www.activestate.com)
     or Strawberry Perl (http://strawberryperl.com).

Added: trunk/Master/texmf-dist/doc/support/fontools/splitttc
===================================================================
--- trunk/Master/texmf-dist/doc/support/fontools/splitttc	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/support/fontools/splitttc	2019-06-26 20:41:25 UTC (rev 51473)
@@ -0,0 +1,271 @@
+#! /usr/bin/env perl
+
+=begin COPYRIGHT
+
+----------------------------------------------------------------------------
+
+    Copyright (C) 2019 Marc Penninga.
+
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation, either version 2
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to
+        Free Software Foundation, Inc.,
+        59 Temple Place,
+        Suite 330,
+        Boston, MA 02111-1307,
+        USA
+
+----------------------------------------------------------------------------
+
+=end COPYRIGHT
+
+=cut
+
+use strict;
+use warnings;
+
+use File::Basename;
+use Getopt::Long;
+use Pod::Usage;
+
+my $VERSION = "20190625";
+
+parse_commandline();
+
+use constant {
+    SIZEOF_OFFSET_TABLE =>  12,
+    SIZEOF_TABLE_RECORD =>  16,
+};
+
+my $filename_in = $ARGV[0];
+my ($basename_out, undef, undef) = fileparse($filename_in, qw(.ttc .otc));
+my $output_prefix = $ARGV{output_prefix} // $basename_out;
+
+open my $fh, '<:raw', $filename_in
+    or die "[ERROR] cannot open $filename_in: $!";
+my $ttc = do { local $/; <$fh> };
+close $fh
+    or die "[ERROR] something went wrong when closing $filename_in: $!";
+
+# unpack TTC header; we ignore the DSIG fields in version 2.0 headers
+my ($ttc_tag, $major_version, $minor_version, $num_fonts)
+    = unpack 'A4 nnN', $ttc;
+my $ttc_header_version = sprintf "%d.%d", $major_version, $minor_version;
+die "$ARGV[0] is not an OpenType Collection file" if $ttc_tag ne 'ttcf';
+die "$ARGV[0]: unknown TTC Header Version $ttc_header_version"
+    if $ttc_header_version !~ m/\A [12] [.] 0 \z/xms;
+
+my $offsets_template = sprintf "\@%d N%d", SIZEOF_OFFSET_TABLE, $num_fonts;
+my @offsets_of_offset_table = unpack $offsets_template, $ttc;
+
+# collect the data for each font and write to separate file
+for my $i_font (1..$num_fonts) {
+    my $offset_of_offset_table = $offsets_of_offset_table[$i_font - 1];
+    my $offset_table
+        = substr $ttc, $offset_of_offset_table, SIZEOF_OFFSET_TABLE;
+
+    # unpack relevant fields from Offset Table
+    my ($sfnt_version, $num_tables) = unpack 'a4 n', $offset_table;
+    my $file_ext = $sfnt_version eq 'OTTO'             ? 'otf'
+                 : $sfnt_version eq "\x00\x01\x00\x00" ? 'ttf'
+                 :                                       die
+                 ;
+    my $filename_out = sprintf "%s%d.%s", $output_prefix, $i_font, $file_ext;
+
+    # unpack Table Records and create list of tables
+    my $table_records
+        = substr $ttc,
+                 $offset_of_offset_table + SIZEOF_OFFSET_TABLE,
+                 $num_tables * SIZEOF_TABLE_RECORD,
+                 ;
+    my $table_records_template
+        = sprintf "(a%d)%d", SIZEOF_TABLE_RECORD, $num_tables;
+    my @table_records = unpack $table_records_template, $table_records;
+    for my $table_record (@table_records) {
+        my ($table_tag, $checksum, $offset, $length)
+            = unpack 'a4 N3', $table_record;
+        my $padding = "\x00" x ((4 - ($length % 4)) % 4);
+        my $table = substr($ttc, $offset, $length) . $padding;
+        $table_record = {
+            table_tag   =>  $table_tag,
+            checksum    =>  $checksum,
+            offset      =>  $offset,
+            length      =>  $length,
+            table       =>  $table,
+        };
+    }
+
+    my $file_pos = SIZEOF_OFFSET_TABLE + length $table_records;
+    for my $table_record (@table_records) {
+        $table_record->{offset} = $file_pos;
+        $file_pos += length $table_record->{table};
+    }
+
+    open my $filehandle_out, '>:raw', $filename_out
+        or die "[ERROR] Cannot create $filename_out: $!";
+    print {$filehandle_out} $offset_table;
+    for my $table_record (@table_records) {
+        print {$filehandle_out}
+            pack 'a4 N3',
+                 @{$table_record}{ qw(table_tag checksum offset length) }
+            ;
+    }
+    for my $table_record (@table_records) {
+        print {$filehandle_out} $table_record->{table};
+    }
+    close $filehandle_out
+        or die "[ERROR] something went wrong when closing $filename_out: $!";
+}
+
+#-----------------------------------------------------------------------
+# Read the command-line options
+#-----------------------------------------------------------------------
+sub parse_commandline {
+    Getopt::Long::GetOptions(
+        'help|?'            =>  sub { pod2usage(-verbose => 1) },
+        'version'           =>  sub { print "$VERSION\n"; exit },
+        'output-prefix=s'   => \$ARGV{output_prefix},
+    )
+    or pod2usage(-verbose => 0);
+
+    pod2usage(-verbose => 0) if @ARGV != 1;
+
+    return;
+}
+
+
+__END__
+
+
+############################################################################
+
+    To create the documentation:
+
+    pod2man --center="Marc Penninga" --release="fontools" --section=1 \
+        splitttc - | groff -Tps -man - | ps2pdf - splitttc.pdf
+
+=pod
+
+=head1 NAME
+
+splitttc - split an OpenType Collection F<ttc> or F<otc> file
+
+=head1 SYNOPSIS
+
+=over 8
+
+=item B<splitttc>
+[B<-help>]
+[B<-version>]
+[B<-output-prefix>=I<< <prefix> >>]
+B<< <ttc-or-otc-file> >>
+
+=back
+
+
+=head1 DESCRIPTION
+
+B<splitttc> splits an OpenType Collection file.
+
+The OpenType specification allows for multiple fonts to be contained
+in the same file. This might be advantageous if fonts share a lot of data,
+as this then needs to be stored only once. Probably the best known
+example of an OpenType Collection file is Microsoft's Cambria,
+where the Regular weight shares a file with the Math font.
+
+Unfortunately some tools (including Eddie Kohler's LCDF TypeTools)
+cannot handle such OpenType Collections; they only work for individual fonts.
+B<splitttc> takes an OpenType Collection file
+and splits it into its constituent parts.
+
+=head1 OPTIONS AND ARGUMENTS
+
+=over 4
+
+=item B<-help>
+
+Print a short description of the syntax and exit.
+
+=item B<-version>
+
+Print version number and exit.
+
+=item B<-output-prefix>=I<< <prefix> >>
+
+Write the individual fonts to files named I<< <prefix> >>1.ttf,
+I<< <prefix> >>2.ttf etc.
+The default is to take the prefix from the filename of the input file.
+
+=item B<< <ttc-or-otc-file> >>
+
+The F<ttc> or F<otc> file to be split.
+
+=back
+
+You may use either one or two dashes before options,
+and option names may be shortened to a unique prefix.
+
+
+=head1 AUTHOR
+
+Marc Penninga <marcpenninga at gmail.com>
+
+
+=head1 COPYRIGHT
+
+Copyright (C) 2019 Marc Penninga.
+
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published
+by the Free Software Foundation, either version 2 of the License,
+or (at your option) any later version.
+A copy of the GNU General Public License is included with B<splitttc>;
+see the file F<GPLv2.txt>.
+
+
+=head1 DISCLAIMER
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+
+=head1 VERSION
+
+This document describes B<splitttc> version 20190625.
+
+
+=head1 RECENT CHANGES
+
+(See the source code for the rest of the story.)
+
+=over 12
+
+=item I<2019-06-25>
+
+First release.
+
+=back
+
+
+=begin Really_old_history
+
+=over 12
+
+=back
+
+=cut
+


Property changes on: trunk/Master/texmf-dist/doc/support/fontools/splitttc
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t3.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t3.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t3.enc	2019-06-26 20:41:25 UTC (rev 51473)
@@ -0,0 +1,276 @@
+% A version of the T3 encoding, intended for use with otftotfm.
+% CODINGSCHEME IPA ENCODING
+/otftotfmT3Encoding [
+% 0x00
+/uni02CB
+/uni02CA
+/uni02C6
+/uni02DC
+/dieresis
+/uni02BA
+/uni02DA
+/uni02C7
+/uni02D8
+/uni02C9
+/uni02D9
+/cedilla
+/uni02DB
+/space_uni030F
+/subgrave
+/subacute
+% 0x10
+/space_uni0311
+/space_uni032A
+/space_uni033A
+/space_uni033B
+/uni02BE
+/uni02BF
+/space_uni032B
+/space_uni033C
+/uni02DF
+/dotlessi
+/dotlessj
+/uni02D6
+/uni02D4
+/uni02D5
+/advancing
+/retracting
+% 0x20
+/celpal
+/uni01C3
+/uni02C8
+/hooktop
+/space_uni0322
+/space_uni0321
+/uni0360
+/quoteright
+/parenleft
+/parenright
+/asterisk
+/plus
+/comma
+/hyphen
+/period
+/slash
+% 0x30
+/uni0289
+/uni0268
+/uni028C
+/uni025C
+/uni0265
+/uni0250
+/uni0252
+/uni0264
+/uni0275
+/uni0258
+/uni02D0
+/uni02D1
+/uni203F
+/equal
+/uni2322
+/question
+% 0x40
+/uni0259
+/uni0251
+/beta.ipa
+/uni0255
+/eth
+/uni025B
+/uni0278
+/uni0263
+/uni0266
+/uni026A
+/uni029D
+/uni0281
+/uni028E
+/uni0271
+/eng.ipa
+/uni0254
+% 0x50
+/uni0294
+/uni0295
+/uni027E
+/uni0283
+/theta.ipa
+/uni028A
+/uni028B
+/uni026F
+/chi.ipa
+/uni028F
+/uni0292
+/bracketleft
+/uni02BD
+/bracketright
+/uni02FA
+/uni02F9
+% 0x60
+/uni02BB
+/a
+/b
+/c
+/d
+/e
+/f
+/uni0261
+/h
+/i
+/j
+/k
+/l
+/m
+/n
+/o
+% 0x70
+/p
+/q
+/r
+/s
+/t
+/u
+/v
+/w
+/x
+/y
+/z
+/uni01C1
+/uni01C0
+/uni01C2
+/uni02DE
+/uni02CC
+% 0x80
+/longleveltone
+/longfallingtone1
+/longfallingtone2
+/longfallingtone3
+/longfallingtone4
+/longrisingtone1
+/longrisingtone2
+/longrisingtone3
+/longrisingtone4
+/shortleveltone
+/shortfallingtone1
+/shortfallingtone2
+/shortfallingtone3
+/shortfallingtone4
+/shortrisingtone1
+/shortrisingtone2
+% 0x90
+/shortrisingtone3
+/shortrisingtone4
+/uni2502
+/uni2551
+/uniA71C
+/uniA71B
+/uni2197
+/uni2198
+/uni1DC4
+/uni1DC5
+/uni1DC8
+/uni1DC9
+/space_uni030D
+/space_uni030E
+/gravedot
+/dotacute
+% 0xa0
+/uni0180
+/uni0111
+/uni0221
+/uni1D91
+/uni1D07
+/g
+/longilefthook
+/uni0285
+/uni1D0A
+/uni029E
+/uni019A
+/lambda.ipa
+/uni019b
+/lyogh.old
+/uni0235
+/turnce
+% 0xb0
+/omega.ipa
+/omega.sc.ipa
+/uni0286
+/uni01AB
+/uni0236
+/uni02A6
+/uni02AE
+/uni02AF
+/uni0293
+/uni01B9
+/afii10094
+/afii10092
+/uni02C0
+/uni02C2
+/uni02C3
+/pipe.var
+% 0xc0
+/uni1D00
+/uni0188
+/uni0297
+/uni02A4
+/uni025A
+/uni029A
+/uni025E
+/uni025D
+/babygamma.old
+/uni029B
+/uni0267
+/uni029C
+/uni0269
+/bardotlessjold
+/uni0199
+/uni029F
+% 0xd0
+/uni026E
+/uni0277
+/uni01A5
+/uni02A0
+/uni027C
+/uni027A
+/uni01AD
+/uni0276
+/uni0287
+/uni02A7
+/uni1D1C
+/uni0296
+/uni02A1
+/uni02A2
+/uni0225
+/uni01BF
+% 0xe0
+/uni0299
+/uni0253
+/uni0257
+/uni0256
+/uni0260
+/uni0262
+/uni00E6
+/uni00E7
+/uni0127
+/uni025F
+/uni0284
+/uni026B
+/uni026C
+/uni026D
+/uni0270
+/uni0273
+% 0xf0
+/uni0274
+/uni0272
+/uni0298
+/uni027D
+/uni0279
+/uni027B
+/uni0280
+/uni0153
+/uni00F8
+/uni0282
+/uni0288
+/uni028D
+/uni0290
+/uni0291
+/uni00FE
+/uni0195
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_t3.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ts3.enc
===================================================================
--- trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ts3.enc	                        (rev 0)
+++ trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ts3.enc	2019-06-26 20:41:25 UTC (rev 51473)
@@ -0,0 +1,276 @@
+% A version of the TS3 encoding, intended for use with otftotfm.
+% CODINGSCHEME IPA SYMBOL ENCODING
+/otftotfmTS3Encoding [
+% 0x00
+/revpolhook
+/rhooklong
+/palhooklong
+/palhookvar
+/rectanglesuperscript
+/leftarrowsuperscript
+/uni02D7
+/arrowdown.ipa
+/uparrow.ipa
+/uni0362
+/space_uni034D
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x10
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x20
+/uni1D90
+/scriptainverted
+/uniA735
+/uniA72D
+/uni0297.var
+/stretchccurl
+/stretchcvarcurl
+/dfronthook
+/dfronthook.var
+/uni0238
+/uni1D92
+/uni1D93
+/gamma.ipa
+/gammafronttail
+/gammabacktail
+/hhookrtail
+% 0x30
+/uniA727
+/uni027F
+/jcrossedtailvar
+/uni0284.var
+/hm
+/nfrontbar
+/uni019E
+/female
+/uni26B2
+/uni0298.old
+/uni1D97
+/omegainverted
+/plhook
+/uni0239
+/uni01AA
+/tfronthook
+% 0x40
+/invertedtcurl
+/twoturned
+/uni01BA
+/threeturned
+/invertedglotstopcurl
+/glotstopturned
+/pipe.var
+/uni01C1.var
+/uni01C2.var
+/lr
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x50
+/thorn.var1
+/thorn.var2
+/thorn.var3
+/thorn.var4
+/uni0294.var1
+/uni0294.var2
+/uni0294.var3
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x60
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x70
+/ascinverted
+/ao.sc
+/delta.sc.ipa
+/uniA730
+/uni1D0B
+/kscturned
+/lscreversed
+/uni1D0D
+/uni1D18
+/q.sc.ipa
+/uni1D19
+/uscturned
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x80
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0x90
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xa0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xb0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xc0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xd0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xe0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+% 0xf0
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+/.notdef
+] def


Property changes on: trunk/Master/texmf-dist/fonts/enc/dvips/fontools/fontools_ts3.enc
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/scripts/fontools/afm2afm
===================================================================
--- trunk/Master/texmf-dist/scripts/fontools/afm2afm	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/scripts/fontools/afm2afm	2019-06-26 20:41:25 UTC (rev 51473)
@@ -37,7 +37,7 @@
 use Getopt::Long;
 use Pod::Usage;
 
-my $VERSION = "20190522";
+my $VERSION = "20190625";
 
 parse_commandline();
 
@@ -75,7 +75,7 @@
 sub parse_commandline {
     Getopt::Long::GetOptions(
         'help|?'     =>  sub { pod2usage(-verbose => 1) },
-        'version'    =>  sub { print "$VERSION\n"; exit; },
+        'version'    =>  sub { print "$VERSION\n"; exit },
         'encoding=s' => \$ARGV{encoding},
         'kpx=s'      => \$ARGV{kpx},
         'output=s'   => \$ARGV{output},
@@ -321,10 +321,10 @@
 
 [B<-help>]
 [B<-version>]
-[B<-encoding> I<encodingfile>]
-[B<-kpx> I<kpxfile>]
-[B<-output> I<outputfile>]
-B<afmfile>
+[B<-encoding>=I<< <encodingfile> >>]
+[B<-kpx>=I<< <kpxfile> >>]
+[B<-output>=I<< <outputfile> >>]
+B<< <afmfile> >>
 
 =back
 
@@ -360,28 +360,28 @@
 
 Print version number and exit
 
-=item B<-encoding> I<encodingfile>
+=item B<-encoding>=I<< <encodingfile> >>
 
-Re-encode to the enconding in I<encodingfile>
+Re-encode to the enconding in I<< <encodingfile> >>
 
-=item B<-kpx> I<kpxfile>
+=item B<-kpx>=I<< <kpxfile> >>
 
-Read additional kerning pairs from I<kpxfile> and add these to the output.
+Read additional kerning pairs from I<< <kpxfile> >> and add these to the output.
 This option cannot be used to override values from the input F<afm> file,
 since B<afm2afm> will write both old and new values to the output!
 
-The I<kpxfile> should contain kerning data in standard F<afm> format,
+The I<< <kpxfile> >> should contain kerning data in standard F<afm> format,
 i.e. for each kerning pair there should be a line
 
     KPX <left_glyph> <right_glyph> <amount>
 
-All other lines in the I<kpxfile> are ignored.
+All other lines in the I<< <kpxfile> >> are ignored.
 
-=item B<-output> I<outputfile>
+=item B<-output>=I<< <outputfile> >>
 
-Write the result to I<outputfile> instead of C<stdout>.
+Write the result to I<< <outputfile> >> instead of C<stdout>.
 
-=item B<afmfile>
+=item B<< <afmfile> >>
 
 The F<afm> file to be re-encoded.
 
@@ -421,7 +421,7 @@
 
 =head1 VERSION
 
-This document describes B<afm2afm> version 20190522.
+This document describes B<afm2afm> version 20190625.
 
 
 =head1 RECENT CHANGES

Modified: trunk/Master/texmf-dist/scripts/fontools/autoinst
===================================================================
--- trunk/Master/texmf-dist/scripts/fontools/autoinst	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/scripts/fontools/autoinst	2019-06-26 20:41:25 UTC (rev 51473)
@@ -40,7 +40,7 @@
 use Pod::Usage ();
 use POSIX ();
 
-my $VERSION = '20190522';
+my $VERSION = '20190625';
 
 my ($d, $m, $y) = (localtime time)[3 .. 5];
 my $TODAY = sprintf "%04d/%02d/%02d", $y + 1900, $m + 1, $d;
@@ -50,34 +50,48 @@
     Some fontnames contain abbreviated words for width, weight and/or shape;
     we unabbreviate these using the following table.
 
+    To avoid having to have this information in multiple places,
+    we also build a reversed table %ABBREV that maps 'full' forms
+    to all known abbreviations; we then inject these abbreviations into
+    the %NFSS_WEIGHT, %NFSS_WIDTH and %NFSS_SHAPE tables below,
+    so that they recognise the abbreviated forms as well as the full ones.
+
 =end Comment
 
 =cut
 
 my %UNABBREVIATE = (
-    demi    =>  'demibold',
-    hair    =>  'hairline',
-    ultra   =>  'ultrablack',
     cmp     =>  'compressed',
     comp    =>  'compressed',
     cond    =>  'condensed',
+    demi    =>  'demibold',
+    extcond =>  'extracondensed',
+    hair    =>  'hairline',
+    incline =>  'inclined',
     it      =>  'italic',
     ita     =>  'italic',
+    md      =>  'medium',
     slant   =>  'slanted',
-    incline =>  'inclined',
+    ultra   =>  'ultrablack',
 );
+my %ABBREV;
+while ( my ($k, $v) = each %UNABBREVIATE ) {
+    push @{$ABBREV{$v}}, $k;
+}
+for my $full (keys %ABBREV) {
+    push @{$ABBREV{$full}}, $full;
+}
 
 =begin Comment
 
-    LaTeX's NFSS contains a limited number of standard codes for weight and width:
+    LaTeX's NFSS contains a number of standard codes for weight and width:
     - weight: ul, el, l, sl, m, sb, b, eb, ub
     - width:  uc, ec, c, sc, m, sx, x, ex, ux
 
-    These codes are not always a good match with the weights and widths
-    actually present in a font family; some families (especially sans-serif ones)
-    contain too many weights and widths, and the naming of those weights and
-    widths isn't always consistent between font families.
-
+    These codes are not always a perfect match with the weights and widths
+    present in a font family; some families (especially sanserif ones)
+    contain more or different weights and widths, and the naming of those
+    weights and widths isn't always consistent between font families.
     To handle this situation, we use a two-tiered approach:
     1.  We install all fonts using a "series" name that is the concatenation
         of whatever the font designer has chosen to call the weight and width
@@ -94,91 +108,75 @@
 
         sc  =>  [ qw( semicondensed narrow ) ],
 
-    This should be read as follows: the NFSS code "sc" is mapped to the *first*
-    width on the right hand side that is present in the current font family.
+    This should be read as follows: the NFSS code "sc" is mapped to
+    the *first* width on the right hand side present in the current family.
 
-    Please note that the tables contain empty keys instead of "m" for
-    the regular weight and width. NFSS actually combines weight and width
-    into a single "series" attribute; a weight or width of "m" is left out of
+    Please note that the tables contain empty keys instead of "m" for the
+    regular weight and width. NFSS actually combines weight and width into
+    a single "series" attribute; a weight or width of "m" is left out of
     this combination (unless *both* weight and width are equal to "m"; then
     the series becomes "m", but that's a special case we deal with later on).
 
     In addition to the mapping of NFSS codes, the two mentioned tables are
-    also used in parsing the font's metadata to determine its weight and width:
-    any string that occurs on the right hand side is considered a possible name
-    to be searched for.
+    also used in parsing the font's metadata to determine its weight and
+    width: any string that occurs on the right hand side is considered a
+    possible name to be searched for.
 
-    These tables can be extended to teach autoinst about new weights or widths.
-    Suppose your font family contains a "Hemibold" weight. Then add the name
-    "hemibold" to the right hand side of the "sb" entry in the NFSS_WEIGHT
-    table:
+    These tables can be extended to teach autoinst about new weights or
+    widths.  Suppose your font family contains a "Hemibold" weight, that
+    you want mapped to the "sb" code. Then add the name "hemibold" to
+    the right hand side of the "sb" entry in the NFSS_WEIGHT table:
 
         sb  =>  [ qw( semibold demi demibold medium hemibold ) ],
 
-    In this case, since it's in last position, it's only mapped to "sb" if none of
-    the other fonts are present. Put it earlier in the list to give it higher
-    priority (or put it in another entry if you'd rather see it mapped to another
-    NFSS code).
+    In this case, since it's in last position, it's only mapped to "sb"
+    if none of the other fonts are present. Put it earlier in the list
+    to give it higher priority.
 
-    Note that autoinst converts all metadata to lowercase to avoid inconsistent
-    capitalization; so all entries in these tables should be *lowercase* as well.
+    Note that autoinst converts all metadata to lowercase to avoid
+    inconsistent capitalization; so all entries in these tables should
+    be *lowercase* as well.
 
-    Technical note:
-    We define NFSS_WEIGHT and NFSS_WIDTH first as arrays and then as hashtables;
-    this allows us to use the array-variants as an *ordered* list of keys.
+    Technical notes:
+    -   We define NFSS_WEIGHT and NFSS_WIDTH first as arrays
+        and then as hashtables; this allows us to use the array-variants
+        as an *ordered* (by weight/width) list of values.
+    -   We exclude the Medium and Regular weights and widths
+        from the @WEIGHTS and @WIDTHS arrays to avoid false positives;
+        see the comments in the parse_basicinfo() function.
 
-
-    Finally, some random remarks about these tables:
-    - Poster and Super aren't just "very heavy" weights; in most cases, they're
-        more like separate designs. The same holds for the Compact width.
-        I added them for completeness.
-    - Two, Four and Eight are (experimental) weights that only occur in Fira Sans.
-    - Some families (Helvetica, Univers) treat Thin as a synonym for Extralight;
-        mostly, however, it is a very light weight below Ultralight.
-    - Semilight weights are virtually nonexistent, except for Thesis
-        (which contains a Semilight weight) and Arnhem (which has Blond).
-    - Book is usually slightly lighter than Regular, but sometimes
-        (mainly in fonts from DTL and FontFont/FSI) slightly *heavier*.
-    - Likewise, Medium can really be two different things:
-        - a synonym for Semibold
-        - (especially in newer fonts) an extra step between Regular and Semibold
-        I treat it as if it's always the first.
-    - Heavy can mean very different things; it's often heavier than Black,
-        but sometimes it's a synonym for Extrabold, and in Futura it's even
-        lighter than Bold. I treat it here as "very black".
-    - Font families that have both Condensed and Compressed widths
-        seem to define Compressed as narrower than Condensed.
-    - In Basic Sans and Input (which are the only families I know with both
-        Narrow and Condensed), Narrow is a bit wider than Condensed.
-        So I mapped Narrow to "sc".
-    - Extended and Expanded seem to be used interchangeably.
-    - I have never seen any (Extra-,Ultra)(Extended,Expanded,Wide) fonts,
-        so the ex and ux entries are currently empty.
-
 =end Comment
 
 =cut
 
 my @NFSS_WEIGHT = (
-    ul  =>  [ qw( ultralight thin hair hairline eight four two ) ],
+    ul  =>  [ qw( ultralight thin hairline eight four two ) ],
     el  =>  [ qw( extralight ) ],
     l   =>  [ qw( light ) ],
     sl  =>  [ qw( semilight blond ) ],
     ''  =>  [ qw( regular text book ) ],
-    sb  =>  [ qw( semibold demi demibold medium ) ],
+    sb  =>  [ qw( semibold demibold medium ) ],
     b   =>  [ qw( bold ) ],
     eb  =>  [ qw( extrabold ) ],
-    ub  =>  [ qw( ultrabold black heavy extrablack ultra ultrablack ultraheavy
-                  poster super ) ],
+    ub  =>  [ qw( ultrabold black heavy extrablack ultrablack
+                  ultraheavy poster super ) ],
 );
 my %NFSS_WEIGHT = @NFSS_WEIGHT;
 @NFSS_WEIGHT = grep { !ref } @NFSS_WEIGHT;
-my @WEIGHTS = map { @{$_} } values %NFSS_WEIGHT;
 
+# Add abbreviated forms, using the %ABBREV table constructed earlier
+for my $code (@NFSS_WEIGHT) {
+    $NFSS_WEIGHT{$code}
+        = [ map { @{ $ABBREV{$_} // [$_] } } @{$NFSS_WEIGHT{$code}} ];
+}
+
+my @WEIGHTS = grep { $_ !~ m/ regular | medium /xms }
+                   map { @{$_} } values %NFSS_WEIGHT;
+
 my @NFSS_WIDTH = (
     uc  =>  [ qw( ultracondensed extracompressed ultracompressed ) ],
-    ec  =>  [ qw( extracondensed cmp comp compressed compact ) ],
-    c   =>  [ qw( cond condensed ) ],
+    ec  =>  [ qw( extracondensed compressed compact ) ],
+    c   =>  [ qw( condensed ) ],
     sc  =>  [ qw( semicondensed narrow ) ],
     ''  =>  [ qw( regular ) ],
     sx  =>  [ qw( semiextended semiexpanded ) ],
@@ -188,8 +186,15 @@
 );
 my %NFSS_WIDTH = @NFSS_WIDTH;
 @NFSS_WIDTH = grep { !ref } @NFSS_WIDTH;
-my @WIDTHS = map { @{$_} } values %NFSS_WIDTH;
 
+# Add abbreviated forms, using the %ABBREV table constructed earlier
+for my $code (@NFSS_WIDTH) {
+    $NFSS_WIDTH{$code}
+        = [ map { @{ $ABBREV{$_} // [$_] } } @{$NFSS_WIDTH{$code}} ];
+}
+
+my @WIDTHS = grep { $_ ne 'regular' } map { @{$_} } values %NFSS_WIDTH;
+
 =begin Comment
 
     The NFSS_SHAPE table maps various shape names to NFSS codes.
@@ -200,8 +205,8 @@
     we might have multiple weighs or widths mapping to the same code,
     and we need a way to prioritise some weights/widths over others.
 
-    For shapes, that's not the case; font families don't have both Slanted and
-    Oblique shapes, since these are just different names for the same thing.
+    For shapes, that's not the case; font families don't have both Slanted
+    and Oblique shapes, since these are different names for the same thing.
 
     Like in the other NFSS_* tables, entries may be added to teach autoinst
     about new shapes.
@@ -214,19 +219,22 @@
     roman       =>  'n',
     upright     =>  'n',
     italic      =>  'it',
-    ita         =>  'it',
-    it          =>  'it',
     cursive     =>  'it',
     kursiv      =>  'it',
     inclined    =>  'sl',
-    incline     =>  'sl',
     oblique     =>  'sl',
     slanted     =>  'sl',
-    slant       =>  'sl',
-    romani      =>  'n',    # Silentium Pro has two roman shapes, but no italic;
-    romanii     =>  'it',   # so we cheat by mapping the second roman shape to 'it'
+    romani      =>  'n',    # Silentium has two roman shapes, but no italic;
+    romanii     =>  'it',   # so we cheat by mapping the second roman to 'it'
 );
 my %NFSS_SHAPE = @NFSS_SHAPE;
+for my $full (keys %ABBREV) {
+    if (defined $NFSS_SHAPE{$full}) {
+        for my $abbrev ( @{$ABBREV{$full}} ) {
+            $NFSS_SHAPE{$abbrev} = $NFSS_SHAPE{$full};
+        }
+    }
+}
 
 =begin Comment
 
@@ -319,8 +327,8 @@
 
     Each key in this table names a figure style; the corresponding
     value is an anonymous hash with four key/value pairs:
-        reqd    A list of required OpenType features;
-                this style is built if the font supports *all* these features.
+        reqd    A list of required OpenType features; this style is built
+                if the font supports *all* these features.
         nice    A list of optional OpenType features;
                 these are used if the font supports them, but don't
                 prevent this style from being built when missing.
@@ -458,6 +466,8 @@
     ARGV::parse_options();
 
     my @fonts = map { Fontinfo::parse_fontinfo($_) } @ARGV;
+
+    create_logfile(@fonts);
     Fontinfo::assert_unique(@fonts);
 
     # We can only handle the '-inferiors=auto' option now,
@@ -489,7 +499,7 @@
     # Decide to which weights and widths we'll map the standard NFSS codes
     decide_nfss_mappings(@fonts);
 
-    create_logfile(@worklist);
+    log_worklist(@worklist);
 
     if (!$ARGV{dryrun}) {
         # Create the LaTeX support files
@@ -513,8 +523,8 @@
 # Return a list with all unique entries from the input
 #-----------------------------------------------------------------------
 sub uniq {
-    my %tmp = map { ($_ => 1) } @_;
-    return keys %tmp;
+    my %seen;
+    return grep { !$seen{$_}++ } @_;
 }
 
 #-----------------------------------------------------------------------
@@ -597,21 +607,21 @@
 sub cleanup {
     my @worklist = @_;
 
+    WORKITEM:
     for my $item (@worklist) {
         my ($font, $style, $shape, $encoding)
             = @{$item}{qw(font style shape encoding)};
 
-        # make unique copy of fontdata, since we're modifying it;
-        # otherwise, the mergesmallcaps option only works for
-        # the first encoding in the list
-        my %font = %$font;
-        $font = $item->{font} = \%font;
-
-        # handle fonts that put small caps fonts into separate family
-        if ($ARGV{mergesmallcaps}) {
-            if ($font->{family} =~ s/(?: smallcaps | sc )$//xmsi) {
-                $shape = $item->{shape} = 'smallcaps';
+        # don't generate smallcaps version of TS1-encoded fonts,
+        # as these contain the same glyphs as the regular version
+        if ($font->{is_smallcaps}) {
+            if ($shape eq 'textcomp') {
+                $item = 0;
+                next WORKITEM;
             }
+            else {
+                $shape = 'smallcaps';
+            }
         }
 
         # generate unique name for this font
@@ -637,13 +647,14 @@
         $item->{features} = [ sort keys %feature ];
 
         # add finishing touches to name and NFSS code of encoding
-        $item->{encoding}[0] =~ s/\A (ot1|t1|ly1|lgr|t2[abc]) \z/fontools_$1/xms;
+        $item->{encoding}[0]
+            =~ s/\A (ot1|t1|ly1|lgr|t2[abc]|t3|ts3) \z/fontools_$1/xms;
         $item->{encoding}[1] = uc $item->{encoding}[1];
 
         $item->{cmdline} = make_cmdline($item);
     }
 
-    return @worklist;
+    return grep { $_ } @worklist;
 }
 
 #-----------------------------------------------------------------------
@@ -652,37 +663,65 @@
 sub decide_nfss_mappings {
     my ( %weight, %width );
     for my $font (@_) {
-        $weight{ $font->{weight} } = 1;
-        $width{ $font->{width} } = 1;
+        $weight{ $font->{weight} } //= $font->{weight_class};
+        $width{ $font->{width} } //= $font->{width_class};
     }
 
     NFSSWEIGHT:
     for my $nfssweight (@NFSS_WEIGHT) {
-        for my $weight ( @{$NFSS_WEIGHT{$nfssweight}} ) {
-            if ( $weight{$weight} ) {
-                $NFSS_WEIGHT{$nfssweight} = [ $weight ];
-                next NFSSWEIGHT;
-            }
-        }
-        $NFSS_WEIGHT{$nfssweight} = [];
+        $NFSS_WEIGHT{$nfssweight}
+            = [ grep { $weight{$_} } @{$NFSS_WEIGHT{$nfssweight}} ];
     }
+
+    # Some trickery to handle the case where the ul/ub codes are mapped
+    # but the el/eb codes are still empty. We try two things:
+    # 1.  if there is a Thin (Heavy) weight and this is less extreme
+    #     than the weight mapped to ul (ub), we map Thin (Heavy) to ul (ub)
+    # 2.  otherwise we move the ul/ub weight to the el/eb position,
+    #     unless that weight is the Ultralight/Ultrabold weight
     if ( !$ARGV{el} and !$ARGV{ul} ) {
-        if ( @{$NFSS_WEIGHT{ul}}
-                and $NFSS_WEIGHT{ul}[0] ne 'ultralight'
-                and !@{$NFSS_WEIGHT{el}} ) {
-            $NFSS_WEIGHT{el} = $NFSS_WEIGHT{ul};
-            $NFSS_WEIGHT{ul} = [];
+        if ( @{$NFSS_WEIGHT{ul}} and !@{$NFSS_WEIGHT{el}} ) {
+            if ( $weight{thin}
+                    and $weight{thin} > $weight{$NFSS_WEIGHT{ul}[0]} ) {
+                $NFSS_WEIGHT{el} = [ 'thin', ];
+            }
+            elsif ( $NFSS_WEIGHT{ul}[0] ne 'ultralight' ) {
+                $NFSS_WEIGHT{el} = [ shift @{$NFSS_WEIGHT{ul}} ];
+            }
         }
     }
     if ( !$ARGV{eb} and !$ARGV{ub} ) {
-        if ( @{$NFSS_WEIGHT{ub}}
-                and $NFSS_WEIGHT{ub}[0] ne 'ultrabold'
-                and !@{$NFSS_WEIGHT{eb}} ) {
-            $NFSS_WEIGHT{eb} = $NFSS_WEIGHT{ub};
-            $NFSS_WEIGHT{ub} = [];
+        if ( @{$NFSS_WEIGHT{ub}} and !@{$NFSS_WEIGHT{eb}} ) {
+            if (    $weight{heavy}
+                and $weight{heavy} < $weight{$NFSS_WEIGHT{ub}[0]}
+            ) {
+                $NFSS_WEIGHT{eb} = [ 'heavy', ]
+                    unless @{$NFSS_WEIGHT{b}}
+                       and $weight{$NFSS_WEIGHT{b}[0]} > $weight{heavy};
+            }
+            elsif ( $NFSS_WEIGHT{ub}[0] ne 'ultrabold' ) {
+                $NFSS_WEIGHT{eb} = [ shift @{$NFSS_WEIGHT{ub}} ];
+            }
         }
     }
 
+    # Special case: if we don't have Regular but we *do* have Medium,
+    # move Medium from the "sb" list to the "m" (i.e., Regular) one.
+    if ( !@{$NFSS_WEIGHT{''}} and $weight{medium} ) {
+        $NFSS_WEIGHT{''} = [ 'medium' ];
+        $NFSS_WEIGHT{sb}
+            = [ grep { $_ ne 'medium' } @{$NFSS_WEIGHT{medium}} ];
+    }
+
+    # Some more trickery to map the sl code to Book or Text (but of course
+    # only if sl is empty and Book/Text is lighter than Regular)
+    if ( !@{$NFSS_WEIGHT{sl}} ) {
+        $NFSS_WEIGHT{sl}
+            = [ grep { $weight{$_} < $weight{$NFSS_WEIGHT{''}[0]} }
+                     @{$NFSS_WEIGHT{''}}
+            ];
+    }
+
     NFSSWIDTH:
     for my $nfsswidth (@NFSS_WIDTH) {
         for my $width ( @{$NFSS_WIDTH{$nfsswidth}} ) {
@@ -696,18 +735,14 @@
 }
 
 #-----------------------------------------------------------------------
-# Dump all relevant info to the logfile
+# Log all fonts, styles, encodings etc. we're  going to create
 #-----------------------------------------------------------------------
 sub create_logfile {
-    my @worklist
-        = sort { $a->{font}{filename} cmp $b->{font}{filename}
-                    || $a->{encoding}[1] cmp $b->{encoding}[1]
-                    || $a->{style} cmp $b->{style}
-               } @_;
+    my @fonts = @_;
 
     if (-e $ARGV{logfile}) {
-        print "[INFO]: file '$ARGV{logfile}' already exists;\n" .
-              "        appending new log data to end\n\n";
+        print "[INFO] file '$ARGV{logfile}' already exists;\n" .
+              "       appending new log data to end\n\n";
     }
     open my $LOG, '>>', $ARGV{logfile}
         or die "$0: cannot create $ARGV{logfile}: $!";
@@ -720,13 +755,10 @@
 
 @{[ POSIX::strftime("[%F %T]", localtime time) ]}  $0, version $VERSION
 
-
     "$ARGV{cmdline}"
 
-
 ----------------------------------------------------------------------------
 
-
 I'm using the following options:
 
     encoding(s):        @{[ join ', ', @{$ARGV{encoding}} ]}
@@ -755,17 +787,74 @@
     target:             $ARGV{target}
     extra:              @{[ $ARGV{extra} || '<empty>' ]}
 
-    figurekern:         @{[ $ARGV{figurekern}       ? 'no action' : 'remove' ]}
-    mergewidths:        @{[ $ARGV{mergewidths}      ? 'yes' : 'no' ]}
-    mergesmallcaps:     @{[ $ARGV{mergesmallcaps}   ? 'yes' : 'no' ]}
+    figurekern:         @{[ $ARGV{figurekern}   ? 'keep' : 'remove' ]}
+    mergewidths:        @{[ $ARGV{mergewidths}  ? 'yes' : 'no' ]}
+    mergeweights:       @{[ $ARGV{mergeweights} ? 'yes' : 'no' ]}
+    mergeshapes:        @{[ $ARGV{mergeshapes}  ? 'yes' : 'no' ]}
 
+    nfssweight:         @{[ join q{, }, @{$ARGV{nfssweight}} or '-' ]}
+    nfsswidth:          @{[ join q{, }, @{$ARGV{nfsswidth}}  or '-' ]}
 
-    font files:
-        @{[ join "\n        ", @ARGV ]}
-
 END_ARGUMENTS
 
-    printf {$LOG} "\n" . '-' x 76 . "\n\n\nNFSS mappings:\n\n";
+    my %fontfamilies = map { ( $_->{family} => 1 ) } @fonts;
+    my @fontfamilies = keys %fontfamilies;
+    if (scalar @fontfamilies > 1) {
+        warn <<"END_WARNING_MULTIPLE_FAMILIES";
+[WARNING] Your fonts seem to belong to multiple families:
+
+          @{[ join( "\n" . q{ } x 10, sort @fontfamilies ) ]}
+
+          "autoinst" performs best when installing one family at a time.
+          If you think your fonts should all be in the same family,
+          you might have found a bug in autoinst's font info parsing.
+
+          Please see the log file $ARGV{logfile} for details on how
+          the fonts' families, weights, widths and shapes were parsed.
+
+END_WARNING_MULTIPLE_FAMILIES
+
+        # increase verbosity if necessary, to log all relevant info
+        if ($ARGV{verbose} < 1) {
+            $ARGV{verbose} = 1;
+        }
+    }
+
+    $ARGV{logfile} = $LOG;
+
+    return if $ARGV{verbose} < 1;
+
+    print {$LOG} '-' x 76 . "\n\nResults of font info parsing:\n";
+
+    for my $font (@fonts) {
+        print {$LOG} <<"END_PARSE_FONT";
+
+    $font->{filename}
+        Name:       $font->{name}
+        Family:     $font->{family}
+        Weight:     $font->{weight} ($font->{weight_class})
+        Width:      $font->{width}
+        Shape:      $font->{shape} @{[ $font->{is_smallcaps}
+                                            ? '(smallcaps)' : '' ]}
+        Size:       $font->{minsize}-$font->{maxsize}
+        Features:   @{[ join ', ', sort keys %{$font->{feature}} ]}
+END_PARSE_FONT
+    }
+}
+
+#-----------------------------------------------------------------------
+# Log all fonts, styles, encodings etc. we're  going to create
+#-----------------------------------------------------------------------
+sub log_worklist {
+    my @worklist
+        = sort { $a->{font}{filename} cmp $b->{font}{filename}
+                    || $a->{encoding}[1] cmp $b->{encoding}[1]
+                    || $a->{style} cmp $b->{style}
+               } @_;
+
+    my $LOG = $ARGV{logfile};
+
+    print {$LOG} "\n" . '-' x 76 . "\n\nNFSS mappings:\n\n";
     for my $weight (@NFSS_WEIGHT) {
         printf {$LOG} "    %-3s =>  %s\n",
                 $weight || 'm', $NFSS_WEIGHT{$weight}[0] || '';
@@ -777,7 +866,7 @@
     }
     printf {$LOG} "\n";
 
-    return if $ARGV{Verbose} < 1;
+    return if $ARGV{verbose} < 1;
 
     my ($prevfn, $prevsty, $prevenc) = ('') x 3;
     my @cmds;
@@ -788,16 +877,7 @@
     ------------------------------------------------------------------------
 
     $item->{font}{filename}
-        Name:       $item->{font}{name}
-        Family:     $item->{font}{family}
-        Subfamily:  $item->{font}{subfamily}
-        Width:      $item->{font}{width}
-        Weight:     $item->{font}{weight}
-        Shape:      $item->{font}{shape}
-        Size:       $item->{font}{minsize}-$item->{font}{maxsize}
-        Features:   @{[ join ', ', sort keys %{$item->{font}{feature}} ]}
 
-
         Generating these encodings, figure styles and shapes:
 
         ENC     STYLE   SHAPE   FEATURES USED
@@ -808,11 +888,11 @@
             print {$LOG} "\n";
         }
         printf {$LOG} "        %-3s     %-4s    %-4s    %s\n",
-                            $item->{encoding}[1],
-                            $item->{style},
-                            $item->{fdshape},
-                            join(', ', @{$item->{features}}),
-                            ;
+                      $item->{encoding}[1],
+                      $item->{style},
+                      $item->{fdshape},
+                      join(', ', @{$item->{features}}),
+                      ;
         $prevfn  = $item->{font}{filename};
         $prevsty = $item->{style};
         $prevenc = $item->{encoding}[1];
@@ -820,7 +900,7 @@
         push @cmds, $item->{cmdline};
     }
 
-    return if $ARGV{Verbose} < 2;
+    return if $ARGV{verbose} < 2;
     print {$LOG} join "\n\n", @cmds;
     print {$LOG} "\n";
     close $LOG;
@@ -845,7 +925,14 @@
     }
     else {
         if (grep { system $_ } @commands) {
-            warn "[WARNING] 'otftotfm' returned non-zero; something's wrong!\n";
+            warn <<"END_OTFTOTFM_WARNING";
+[WARNING] one or more calls to 'otftotfm' failed;
+          please see the messages above.
+
+          Note that you can safely ignore any warnings
+              "bad UNICODING (‘germandbls’ has no encoding)"
+          or  "bad ligature (‘ff’ has no encoding)"
+END_OTFTOTFM_WARNING
         }
     }
 
@@ -862,6 +949,8 @@
     fontools_t2a => 'TEX CYRILLIC FONT ENCODING - T2A',
     fontools_t2b => 'TEX CYRILLIC FONT ENCODING - T2B',
     fontools_t2c => 'TEX CYRILLIC FONT ENCODING - T2C',
+    fontools_t3  => 'TEX IPA ENCODING',
+    fontools_ts3 => 'TEX IPA SYMBOL ENCODING',
 );
 
 #-----------------------------------------------------------------------
@@ -955,6 +1044,7 @@
     -(no)swash              Toggle creation of swash shape
     -(no)titling            Toggle creation of titling shape
     -(no)superiors          Toggle creation of fonts with superior characters
+    -noinferiors
     -inferiors=[none|auto|subs|sinf|dnom]
                             Use this style for subscripts (see docs)
     -(no)ornaments          Toggle creation of ornament fonts
@@ -978,8 +1068,9 @@
     -manual                 Manual mode (see documentation)
 
     -(no)figurekern         Keep or remove kerns between tabular figures
-    -(no)mergewidths        Merge Condended/Extended subfamilies with main family
-    -(no)mergesmallcaps     Merge small caps subfamilies with main family
+    -(no)mergewidths        Merge Condended/Extended subfamilies with main
+    -(no)mergeweights       Merge separate weights with main family
+    -(no)mergeshapes        Merge separate shapes with main family
 
     -nfssweight=xx=yyyy     Map the "xx" NFSS code to the "yyyy" weight
     -nfsswidth=xx=yyyy      Map the "xx" NFSS code to the "yyyy" width
@@ -987,8 +1078,8 @@
     -help                   Print this text and exit
     -doc                    Print the complete documentation and exit
     -dryrun                 Don't generate fonts, only log what would be done
-    -logfile="FILE"         Write log data to "FILE" (default: <fontfamily>.log)
-    -Verbose                Print more data to log file
+    -logfile="FILE"         Write log to "FILE" (default: <fontfamily>.log)
+    -verbose                Print more data to log file
                             (repeat for even higher verbosity)
     -version                Print version number and exit
     font[s]                 The fonts (.otf or .ttf format) to install.
@@ -999,7 +1090,7 @@
 # Default values for the command-line arguments
 %ARGV = (
     encoding        => 'OT1,T1,LY1',
-    textcomp        => '2',     # 0 = no, 1 = yes, 2 = (enc eq 'T1' ? yes : no)
+    textcomp        => '2',     # 0 = no, 1 = yes, 2 = ('T1' ? yes : no)
     lining          => '1',     # 0 = no, 1 = yes
     oldstyle        => '1',     # 0 = no, 1 = yes
     proportional    => '1',     # 0 = no, 1 = yes
@@ -1008,11 +1099,11 @@
     swash           => '1',     # 0 = no, 1 = yes
     titling         => '1',     # 0 = no, 1 = yes
     superiors       => '1',     # 0 = no, 1 = yes
-    inferiors       => 'none',  # possible values: none, auto, subs, sinf, dnom
+    inferiors       => 'none',  # values: none, auto, subs, sinf, dnom
     ornaments       => '1',     # 0 = no, 1 = yes
     fractions       => '0',     # 0 = no, 1 = yes
-    ligatures       => '2',     # 0 = no, 1 = yes, 2 = (nfss ne 'tt' ? yes : no)
-    nfss            => 'rm',
+    ligatures       => '2',     # 0 = no, 1 = yes, 2 = ('tt' ? no : yes)
+    nfss            => '',
     fig_height      => 'lnum',
     fig_width       => 'tnum',
     extra           => '',
@@ -1025,8 +1116,11 @@
     logfile         => '',
     figurekern      => '1',     # 0 = no, 1 = yes
     mergewidths     => '1',     # 0 = no, 1 = yes
-    mergesmallcaps  => '1',     # 0 = no, 1 = yes
-    Verbose         => 0,
+    mergeweights    => '1',     # 0 = no, 1 = yes
+    mergeshapes     => '1',     # 0 = no, 1 = yes
+    verbose         => 0,
+    nfsswidth       => [],
+    nfssweight      => [],
 );
 
 #-----------------------------------------------------------------------
@@ -1036,9 +1130,9 @@
     $ARGV{cmdline} = join ' ', ($0, @ARGV);
 
     Getopt::Long::GetOptions(
-        'help|?'              =>  sub { print $USAGE; exit; },
-        'version'             =>  sub { print "$VERSION\n"; exit; },
-        'doc'                 =>  sub { Pod::Usage::pod2usage(-Verbose => 2); },
+        'help|?'              =>  sub { print $USAGE; exit },
+        'version'             =>  sub { print "$VERSION\n"; exit },
+        'doc'                 =>  sub { Pod::Usage::pod2usage(-verbose => 2) },
         'encoding=s'          => \$ARGV{encoding},
         'ts1!'                => \$ARGV{textcomp},
         'lining!'             => \$ARGV{lining},
@@ -1049,7 +1143,8 @@
         'swash!'              => \$ARGV{swash},
         'titling!'            => \$ARGV{titling},
         'superiors!'          => \$ARGV{superiors},
-        'inferiors=s'         => \$ARGV{inferiors},
+        'noinferiors'         =>  sub { $ARGV{inferiors} = 'none' },
+        'inferiors:s'         => \$ARGV{inferiors},
         'ornaments!'          => \$ARGV{ornaments},
         'fractions!'          => \$ARGV{fractions},
         'ligatures!'          => \$ARGV{ligatures},
@@ -1069,19 +1164,29 @@
         'manual'              => \$ARGV{manual},
         'figurekern!'         => \$ARGV{figurekern},
         'mergewidths!'        => \$ARGV{mergewidths},
-        'mergesmallcaps!'     => \$ARGV{mergesmallcaps},
+        'mergeweights!'       => \$ARGV{mergeweights},
+        'mergeshapes!'        => \$ARGV{mergeshapes},
+        'mergesmallcaps!'     => \$ARGV{mergeshapes},
         'logfile=s'           => \$ARGV{logfile},
-        'Verbose+'            => \$ARGV{Verbose},
+        'verbose+'            => \$ARGV{verbose},
         'nfssweight=s%'       => sub {
                                      my ( $ignored, $key, $values ) = @_;
+                                     push @{$ARGV{nfssweight}},
+                                          "$key=$values";
                                      my @values = split m/,/, lc $values;
-                                     $NFSS_WEIGHT{$key} = \@values;
+                                     $key = q{} if $key eq 'm';
+                                     $NFSS_WEIGHT{$key}
+                                         = [ @values, @{$NFSS_WEIGHT{$key}} ];
                                      $ARGV{$key} = 'user-defined';
                                  },
         'nfsswidth=s%'        => sub {
                                      my ( $ignored, $key, $values ) = @_;
                                      my @values = split m/,/, lc $values;
-                                     $NFSS_WIDTH{$key} = \@values;
+                                     push @{$ARGV{nfsswidth}},
+                                          "$key=$values";
+                                     $key = q{} if $key eq 'm';
+                                     $NFSS_WIDTH{$key}
+                                         = [ @values, @{$NFSS_WIDTH{$key}} ];
                                      $ARGV{$key} = 'user-defined';
                                  },
     )
@@ -1096,6 +1201,7 @@
     delete $STYLE{Sup}           unless $ARGV{superiors};
     delete $STYLE{Orn}           unless $ARGV{ornaments};
     delete @STYLE{qw(Numr Dnom)} unless $ARGV{fractions};
+    $ARGV{inferiors} ||= 'auto';
     if    ($ARGV{inferiors} eq 'auto') { $STYLE{Inf}{reqd} = ['auto'] }
     elsif ($ARGV{inferiors} eq 'subs') { $STYLE{Inf}{reqd} = ['subs'] }
     elsif ($ARGV{inferiors} eq 'sinf') { $STYLE{Inf}{reqd} = ['sinf'] }
@@ -1120,6 +1226,25 @@
         delete $SHAPE{textcomp};
     }
 
+    # Determine NFSS classification of this family, if the user
+    # didn't explicitly specify it
+    if ( !$ARGV{nfss} ) {
+        # EXPERIMENTAL: parse "post" table to see if font is fixed-width
+        open my $otfinfo, '-|:raw', qq(otfinfo --dump-table 'post' "$ARGV[0]")
+            or die "[ERROR] could not fork(): $!";
+        my $post_table = do { local $/; <$otfinfo> };
+        close $otfinfo
+            or die "[ERROR] 'otfinfo --dump-table post $ARGV[0]' failed";
+
+        my $is_fixed_pitch = unpack '@12N', $post_table;
+
+        $ARGV{nfss} = $is_fixed_pitch                 ? 'tt'
+                    : $ARGV[0] =~ m/mono(?!type)/xmsi ? 'tt'
+                    : $ARGV[0] =~ m/sans/xmsi         ? 'sf'
+                    :                                   'rm'
+                    ;
+    }
+
     # If the user didn't explicitly say anything about ligatures,
     # activate them unless the font is a typewriter font.
     if ($ARGV{ligatures} == 2) {
@@ -1205,12 +1330,13 @@
     my ($filename) = @_;
 
     my $info = {
-        filename  => $filename,
-        width     => 'regular',
-        weight    => 'regular',
-        shape     => 'roman',
-        minsize   => 0,
-        maxsize   => 0,
+        filename     => $filename,
+        width        => 'regular',
+        weight       => 'regular',
+        shape        => 'roman',
+        minsize      => 0,
+        maxsize      => 0,
+        is_smallcaps => 0,
     };
 
     parse_basicinfo($info);
@@ -1230,7 +1356,7 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --info "$info->{filename}")
-        or die "[ERROR] 'otfinfo --info $info->{filename}' failed";
+        or die "[ERROR] could not fork(): $!";
     my %data = map { my ($k,$v) = m/\A\s* ([^:]+?) \s*:\s* ([^\r\n]+)/xms;
                      $k =~ s/\s+//xmsg;
                      $v =~ s/\s+//xmsg;
@@ -1237,7 +1363,8 @@
                      (lc $k => $v);
                    }
                    grep { m/\A\s* [^:]+? \s*:\s* [^\r\n]+/xms } <$otfinfo>;
-    close $otfinfo;
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --info $info->{filename}' failed";
 
     $data{family}    =  $data{preferredfamily} || $data{family};
     $data{subfamily} =  $data{preferredsubfamily} || $data{subfamily};
@@ -1246,33 +1373,47 @@
 
     # clean up family name (it's used in LaTeX command names)
     $data{family}    =~ s/\A(?: Adobe | DTL | FF | ITC | LT | MT)//xms;
+    $data{family}    =~ s/(?: LT | MT)(?: Std | Pro )\z//xms;
+    $data{family}    =~ s/(?<= Kievit ) OT//xms;
+    $data{family}    =~ s/ Std \z//xms;
     $data{family}    =~ s/(\d)/$DIGITS[$1]/xmsge;
     $data{family}    =~ s/[^A-Za-z]+//xmsg;
 
-    my $fullinfo =  lc "$data{subfamily} | $data{fullname}";
+    # Sometimes the relevant info is in Fullname, sometimes in Subfamily;
+    # so we need to test against both
+    my $fullinfo = lc "$data{subfamily} | $data{fullname}";
 
     # We need to be careful when parsing the font info; in particular
     # we must parse 'UltraCondensed' as 'Regular' weight
     # and 'UltraCondensed' width, not as 'Ultra' weight and 'Condensed' width.
-    # The following two rules should prevent accidents:
+    # The following rules should prevent accidents:
     # 1.  Search for matching widths before matching weights
     #     (as none of the widths is a proper substring of some weight)
     # 2.  Remove any recognised search string from the 'fullinfo'
+    # 3.  Test the weights 'medium' and 'regular' *last*, since these strings
+    #     may also occur in Subfamily without indicating the weight;
+    #     so we only take them to mean weight if we find no other hit.
     for my $width ( mqrs(@WIDTHS) ) {
-        if ($fullinfo =~ s/${width}//gxmsi) {
+        if ($fullinfo =~ m/${width}/xms) {
             $info->{width} = $width;
+            my $widths = join '|', mqrs(@WIDTHS);
+            $fullinfo =~ s/${widths}//gxmsi;
             last;
         }
     }
-    for my $weight ( mqrs(@WEIGHTS) ) {
-        if ($fullinfo =~ s/${weight}//gxmsi) {
+    for my $weight ( mqrs(@WEIGHTS), qw(medium regular) ) {
+        if ($fullinfo =~ m/${weight}/xms) {
             $info->{weight} = $weight;
+            my $weights = join '|', mqrs(@WEIGHTS), qw(medium regular);
+            $fullinfo =~ s/${weights}//gxmsi;
             last;
         }
     }
     for my $shape ( mqrs( keys %NFSS_SHAPE ) ) {
-        if ($fullinfo =~ s/${shape}//gxmsi) {
+        if ($fullinfo =~ m/${shape}/xms) {
             $info->{shape} = $shape;
+            my $shapes = join '|', mqrs( keys %NFSS_SHAPE );
+            $fullinfo =~ s/${shapes}//gxmsi;
             last;
         }
     }
@@ -1284,26 +1425,10 @@
     $data{subfamily} =~ s/$info->{weight}//xmsi;
     $data{subfamily} =~ s/$info->{shape}//xmsi;
 
-
     $info->{name}      = $data{postscriptname};
     $info->{family}    = $data{family};
     $info->{subfamily} = $data{subfamily};
 
-    if ( !$ARGV{logfile} ) {
-        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
-    }
-    # Some font families put condensed or extended widths into separate families;
-    # we provide an option to merge these with the 'main' font family.
-    if ($ARGV{mergewidths}) {
-        my $widths = join '|', mqrs(@WIDTHS);
-        if ($info->{width} eq 'regular'
-            && $info->{family} =~ m/(.+?) [ ]* (${widths})$/xmsi)
-        {
-            $info->{family} = $1;
-            $info->{width}  = lc $2;
-        }
-    }
-
     # Take care to unabbreviate weight and width; CondensedUltra fonts
     # might end up as 'ultracondensed' instead of 'ultrablackcondensed'!
     if (exists $UNABBREVIATE{ $info->{width} }) {
@@ -1316,16 +1441,81 @@
         $info->{shape} = $UNABBREVIATE{ $info->{shape} };
     }
 
+    if ($ARGV{mergeshapes}) {
+        my $shapes = join '|', mqrs( qw(it italic) );
+        if ( $info->{family} =~ m/(.+?) (${shapes}) \z/xmsi
+                and ( $info->{shape} eq 'regular'
+                   or $info->{shape} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{shape}  = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+
+        $shapes = join '|', mqrs( qw(sc smallcaps) );
+        if ( $info->{family} =~ m/(.+?) (${shapes}) \z/xmsi ) {
+            $info->{family}       = $1;
+            $info->{is_smallcaps} = 1;
+        }
+    }
+
+    # Some font families put different widths into separate families;
+    # we provide an option to merge these with the 'main' font family.
+    if ($ARGV{mergewidths}) {
+        my $widths = join '|', mqrs(@WIDTHS);
+        if ( $info->{family} =~ m/(.+?) (${widths}) \z/xmsi
+                and ( $info->{width} eq 'regular'
+                   or $info->{width} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{width}  = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+    }
+
+    # Some font families put extreme weights into separate families;
+    # we provide an option to merge these with the 'main' font family.
+    if ($ARGV{mergeweights}) {
+        my $weights = join '|', mqrs(@WEIGHTS), qw(medium regular);
+        if ( $info->{family} =~ m/(.+?) (${weights}) \z/xmsi
+                and ( $info->{weight} eq 'regular'
+                   or $info->{weight} eq ( $UNABBREVIATE{ lc($2) } // lc($2) )
+                )
+        ) {
+            $info->{family} = $1;
+            $info->{weight} = $UNABBREVIATE{ lc($2) } // lc($2);
+        }
+    }
+
+    # Fix confusion about "Text": weight vs part of familyname.
+    # In the latter case, we strip it off anyway.
+    $info->{family} =~ s/text \z//xmsi;
+
+    if ( !$ARGV{logfile} ) {
+        $ARGV{logfile} = sprintf "%s.log", lc $info->{family}
+    }
+
     $info->{basicshape} = $NFSS_SHAPE{$info->{shape}};
 
-    # We define 'series' as 'weight + width'. This matches NFSS, but contradicts
-    # how most fonts are named (which is 'width + weight').
+    # We define 'series' as 'weight + width'. This matches NFSS,
+    # but contradicts how most fonts are named (which is 'width + weight').
     $info->{series}
-        = ($info->{width} eq 'regular')  ? $info->{weight}
+        = ($info->{width}  eq 'regular') ? $info->{weight}
         : ($info->{weight} eq 'regular') ? $info->{width}
         :                                  $info->{weight} . $info->{width}
         ;
 
+    # EXPERIMENTAL: we extract the usWeightClass and usWidthClass
+    # properties from the font's OS/2 table
+    open $otfinfo,
+         '-|:raw',
+         qq(otfinfo --dump-table 'OS/2' "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    my $os2_table = do { local $/; <$otfinfo> };
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --dump-table $info->{filename}' failed";
+    @{$info}{qw(weight_class width_class)} = unpack '@4n @6n', $os2_table;
+
     return;
 }
 
@@ -1332,7 +1522,8 @@
 #-----------------------------------------------------------------------
 # Re-order argument list so that longer strings come before shorter ones
 #
-# This is needed when matching a string against a list of patterns;
+# This is needed when matching a string against a list of patterns
+# where some of the patterns may be substrings of other patterns;
 # then we want the *longest* matching pattern, so we test the patterns
 # in descending order of length.
 #-----------------------------------------------------------------------
@@ -1348,14 +1539,16 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --features "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    %{$info->{feature}} = map { (substr($_, 0, 4) => 1) } <$otfinfo>;
+    close $otfinfo
         or die "[ERROR] 'otfinfo --features $info->{filename}' failed";
-    %{$info->{feature}} = map { (substr($_, 0, 4) => 1) } <$otfinfo>;
-    close $otfinfo;
 
     open $otfinfo, '-|', qq(otfinfo --tables "$info->{filename}")
+        or die "[ERROR] could not fork(): $!";
+    $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
+    close $otfinfo
         or die "[ERROR] 'otfinfo --tables $info->{filename}' failed";
-    $info->{feature}{kern} = 1 if grep { m/\d+ \s+ kern/xms } <$otfinfo>;
-    close $otfinfo;
 
     return;
 }
@@ -1368,11 +1561,12 @@
     my $info = shift;
 
     open my $otfinfo, '-|', qq(otfinfo --optical-size "$info->{filename}")
-        or die "[ERROR] 'otfinfo --optical-size $info->{filename}' failed";
+        or die "[ERROR] could not fork(): $!";
 
-    if (my ($minsize, $maxsize) = <$otfinfo> =~ m/[(] ([\d.]+) \s* pt, \s*
-                                              ([\d.]+) \s* pt  \s* []]/xms )
-    {
+    if (my ($minsize, $maxsize)
+        = <$otfinfo> =~ m/[(] ([\d.]+) \s* pt, \s*
+                              ([\d.]+) \s* pt  \s* []]/xms
+    ) {
     # fix some known bugs
         if ($info->{name} eq 'GaramondPremrPro-It'
             && $minsize == 6 && $maxsize == 8.9)
@@ -1400,7 +1594,8 @@
 
         @{$info}{qw(minsize maxsize)} = ($minsize, $maxsize);
     }
-    close $otfinfo;
+    close $otfinfo
+        or die "[ERROR] 'otfinfo --optical-size $info->{filename}' failed";
 
     return;
 }
@@ -1441,7 +1636,8 @@
     my @fonts = @_;
 
     # These attributes should uniquely identify each font
-    my @attributes = qw(family weight width shape minsize maxsize);
+    my @attributes
+        = qw(family weight width shape minsize maxsize is_smallcaps);
 
     my (%seen, $err_details);
     for my $font (@fonts) {
@@ -1479,10 +1675,11 @@
         # Default ornament names: 'orn.' plus three digits
         my @encoding = map { sprintf "orn.%03d", $_ } 1 .. 256;
 
-        open my $OTFINFO, '-|', qq(otfinfo --glyphs "$font->{filename}")
+        open my $otfinfo, '-|', qq(otfinfo --glyphs "$font->{filename}")
+            or die "[ERROR] could not fork(): $!";
+        chop(my @glyphnames = <$otfinfo>);
+        close $otfinfo
             or die "[ERROR] 'otfinfo --glyphs $font->{filename}' failed";
-        chop(my @glyphnames = <$OTFINFO>);
-        close $OTFINFO;
 
         # Test for some known alternative names (probably not exhaustive)
         my @ornaments
@@ -1907,8 +2104,9 @@
 
 =item -
 
-Four text families (with lining and oldstyle digits, each in both tabular
-and proportional variants), all with the following shapes:
+Four text families (with lining and oldstyle digits,
+each in both tabular and proportional variants),
+all with the following shapes:
 
 =over 2
 
@@ -1944,8 +2142,8 @@
 
 =item -
 
-For each T1-encoded text family: a family of TS1-encoded symbol fonts,
-in roman, italic and slanted shapes.
+For each T1-encoded text family:
+a family of TS1-encoded symbol fonts, in roman, italic and slanted shapes.
 
 =item -
 
@@ -1954,7 +2152,8 @@
 
 =item -
 
-Families with "Titling" characters; these "... replace the default glyphs
+Families with "Titling" characters;
+these "... replace the default glyphs
 with corresponding forms designed specifically for titling.
 These may be all-capital and/or larger on the body,
 and adjusted for viewing at larger sizes"
@@ -2038,16 +2237,16 @@
 see the I<-logfile> command-line option in L</"COMMAND-LINE OPTIONS"> below.
 If this log file already exists, B<autoinst> will append its data to the end
 rather than overwrite it.
-Use the I<-Verbose> command-line option to ask for more detailed info.
+Use the I<-verbose> command-line option to ask for more detailed info.
 
 
 =head2 A note for MiKTeX users
 
 Automatically installing the fonts into a suitable TEXMF tree
-(as B<autoinst> tries to do by default) only works for TeX-installations that use
-the F<kpathsea> library; with TeX distributions that implement their
-own directory searching (such as MiKTeX), B<autoinst> will complain that
-it cannot find the F<kpsewhich> program and move all generated files
+(as B<autoinst> tries to do by default) only works for TeX-installations
+that use the F<kpathsea> library; with TeX distributions that implement
+their own directory searching (such as MiKTeX), B<autoinst> will complain
+that it cannot find the F<kpsewhich> program and move all generated files
 into a subdirectory C<./autoinst_output/> of the current directory.
 If you use such a TeX distribution, you should either move these files
 to their correct destinations by hand, or use the I<-target> option
@@ -2061,11 +2260,11 @@
 
 =head2 A note for MacTeX users
 
-By default, B<autoinst> will try to install all files into the $TEXMFLOCAL tree;
-when this directory isn't user-writable, it will use the $TEXMFHOME tree instead.
-Unfortunately, MacTeX's version of C<updmap-sys>
-(which is called behind the scenes) doesn't search in $TEXMFHOME,
-and hence MacTeX will not find the new fonts.
+By default, B<autoinst> will try to install all generated files into
+the $TEXMFLOCAL tree; when this directory isn't user-writable,
+it will use the $TEXMFHOME tree instead.  Unfortunately, MacTeX's version
+of C<updmap-sys> (which is called behind the scenes) doesn't search
+in $TEXMFHOME, and hence MacTeX will not find the new fonts.
 
 To remedy this, either run B<autoinst> as root (so that it can install
 everything into $TEXMFLOCAL) or manually run C<updmap -user> to tell
@@ -2077,8 +2276,8 @@
 =head2 Using the fonts in your LaTeX documents
 
 B<autoinst> generates a style file for using the fonts in LaTeX documents,
-named F<< <FontFamily>.sty >>. This style file also takes care of loading the
-F<fontenc> and F<textcomp> packages.
+named F<< <FontFamily>.sty >>. This style file also takes care of loading
+the F<fontenc> and F<textcomp> packages.
 To use the fonts, add the command C<<< \usepackage{I<< <FontFamily> >>} >>>
 to the preamble of your document.
 
@@ -2125,7 +2324,7 @@
 you have the F<mweights> package installed.
 
 The style file will also try to load the F<fontaxes> package
-(available on CTAN), which gives easy access to various font shapes and styles.
+(on CTAN), which gives easy access to various font shapes and styles.
 Using the machinery set up by F<fontaxes>, the generated style file
 defines a number of commands (which take the text to be typeset as argument)
 and declarations (which don't take arguments, but affect all text up to
@@ -2141,8 +2340,8 @@
 
 
 In addition, the C<\swshape> and C<\textsw> commands are redefined to place
-swash on F<fontaxes>' secondary shape axis (F<fontaxes> places it on the primary
-shape axis) to make them behave properly when nested, so that
+swash on F<fontaxes>' secondary shape axis (F<fontaxes> places it on the
+primary shape axis) to make them behave properly when nested, so that
 C<\swshape\upshape> will give upright swash.
 
 There are no commands for accessing the numerator and denominator
@@ -2159,8 +2358,8 @@
 To access ornament glyphs, B<autoinst> creates a font-specific encoding file
 F<< <FontFamily>_orn.enc >>,
 but only if that file doesn't yet exist in the current directory.
-This is a deliberate feature that allows you to provide your own
-encoding vector, e.g. if your fonts use non-standard glyph names for ornaments.
+This is a deliberate feature that allows you to provide your own encoding
+vector, e.g. if your fonts use non-standard glyph names for ornaments.
 
 These commands are only generated for existing shapes and number styles;
 no commands are generated for shapes and styles that don't exist,
@@ -2226,7 +2425,7 @@
 Of course, not all 81 combinations of these NFSS weights and widths will map
 to existing fonts;
 and conversely it may not be possible to assign every existing font
-a unique code in a sane way (especially on the weight axis, some font families
+a unique code in a sane way (especially for the weights, some font families
 offer more choices or finer granularity than NFSS's codes can handle;
 e.g., Fira Sans contains fifteen(!) different weights,
 including an additional "Medium" weight between Regular and Semibold).
@@ -2279,7 +2478,7 @@
 If the file already exists, B<autoinst> appends to it;
 it doesn't overwrite an existing file.
 
-=item B<-Verbose> (I<note:> uppercase 'V'!)
+=item B<-verbose>
 
 Add more details to the log file. Repeat this option for even more info.
 
@@ -2294,17 +2493,17 @@
 The default choice of encodings is "OT1,T1,LY1".
 For each encoding, a file F<< <encoding>.enc >> (in all I<lowercase>!)
 should be somewhere where F<otftotfm> can find it. Suitable encoding files
-for OT1, T1/TS1, LY1, LGR and T2A/B/C come with B<autoinst>. (These files are
-called F<fontools_ot1.enc> etc. to avoid name clashes with other packages;
-the "fontools_" prefix may be omitted.)
+for OT1, T1/TS1, LY1, LGR, T2A/B/C and T3/TS3 come with B<autoinst>.
+(These files are called F<fontools_ot1.enc> etc. to avoid name clashes
+with other packages; the "fontools_" prefix may be omitted.)
 
-=item B<-ts1> / B<-nots1>
+=item B<-ts1>/B<-nots1>
 
 Control the creation of TS1-encoded fonts. The default is B<-ts1>
 if the text encodings (see I<-encoding> above) include T1,
 B<-nots1> otherwise.
 
-=item B<-serif> / B<-sanserif> / B<-typewriter>
+=item B<-serif>/B<-sanserif>/B<-typewriter>
 
 Install the font as a serif, sanserif or typewriter font, respectively.
 This changes how you access the font in LaTeX:
@@ -2318,46 +2517,55 @@
 This latter effect cannot be disabled in B<autoinst>;
 if you want typewriter text to be hyphenated, use the F<hyphenat> package.
 
-=item B<-lining> / B<-nolining>
+If none of these options is specified, B<autoinst> tries to guess:
+if the font's filename contains the string "mono"
+or if the field C<isFixedPitch> in the font's I<post> table is True,
+it will select B<-typewriter>;
+else if the filename contains "sans" it selects B<-sanserif>;
+and otherwise it will opt for B<-serif>.
 
+=item B<-lining>/B<-nolining>
+
 Control the creation of fonts with lining figures. The default is
 B<-lining>.
 
-=item B<-oldstyle> / B<-nooldstyle>
+=item B<-oldstyle>/B<-nooldstyle>
 
 Control the creation of fonts with oldstyle figures. The default is
 B<-oldstyle>.
 
-=item B<-proportional> / B<-noproportional>
+=item B<-proportional>/B<-noproportional>
 
 Control the creation of fonts with proportional figures. The default is
 B<-proportional>.
 
-=item B<-tabular> / B<-notabular>
+=item B<-tabular>/B<-notabular>
 
 Control the creation of fonts with tabular figures. The default is
 B<-tabular>.
 
-=item B<-smallcaps> / B<-nosmallcaps>
+=item B<-smallcaps>/B<-nosmallcaps>
 
 Control the creation of small caps fonts. The default is
 B<-smallcaps>.
 
-=item B<-swash> / B<-noswash>
+=item B<-swash>/B<-noswash>
 
 Control the creation of swash fonts. The default is B<-swash>.
 
-=item B<-titling> / B<-notitling>
+=item B<-titling>/B<-notitling>
 
 Control the creation of titling families. The default is B<-titling>.
 
-=item B<-superiors> / B<-nosuperiors>
+=item B<-superiors>/B<-nosuperiors>
 
 Control the creation of fonts with superior characters.
 The default is B<-superiors>.
 
-=item B<-inferiors>=[ B<none> | B<auto> | B<subs> | B<sinf> | B<dnom> ]
+=item B<-noinferiors>
 
+=item B<-inferiors> [= B<none> | B<auto> | B<subs> | B<sinf> | B<dnom> ]
+
 The OpenType standard defines several kinds of digits that might be used
 as inferiors or subscripts: "Subscripts" (OpenType feature "subs"),
 "Scientific Inferiors" ("sinf"), and "Denominators" ("dnom").
@@ -2365,31 +2573,33 @@
 should use for the inferior characters.
 Alternatively, the value "auto" tells B<autoinst> to use the first value
 in "subs", "sinf" or "dnom" that is supported by the font.
-The default value is "none".
+Saying just B<-inferiors> is equivalent to B<-inferiors=auto>;
+otherwise the default is B<-noinferiors>.
 
 I<< If you specify a style of inferiors that isn't present in the font,
 B<autoinst> will fall back to its default behaviour of not creating fonts
 with inferiors at all; it won't try to substitute one of the other styles. >>
 
-=item B<-fractions> / B<-nofractions>
+=item B<-fractions>/B<-nofractions>
 
 Control the creation of fonts with numerators and denominators.
 The default is B<-nofractions>.
 
-=item B<-ligatures> / B<-noligatures>
+=item B<-ligatures>/B<-noligatures>
 
 Some fonts create glyphs for the standard f-ligatures (ff, fi, fl, ffi, ffl),
 but don't provide a "liga" feature to access these.
 This option tells B<autoinst> to add extra C<LIGKERN> rules to
 the generated fonts to enable the use of these ligatures.
-The default is B<-ligatures>, unless the user specified the I<ligatures> option.
+The default is B<-ligatures>,
+unless the user specified the I<ligatures> option.
 
 Specify B<-noligatures> to disable the generation of ligatures even for fonts
 that do contain a "liga" feature.
 
-=item B<-defaultlining> / B<-defaultoldstyle>
+=item B<-defaultlining>/B<-defaultoldstyle>
 
-=item B<-defaulttabular> / B<-defaultproportional>
+=item B<-defaulttabular>/B<-defaultproportional>
 
 Tell B<autoinst> which figure style is the current font family's default
 (i.e., which figures you get when you don't specify any OpenType features).
@@ -2410,22 +2620,19 @@
 Note that this option leads to very long commands (it adds
 one hundred I< --ligkern> options), which may cause problems on some systems.
 
-=item B<-mergewidths> / B<-nomergewidths>
+=item B<-mergewidths>/B<-nomergewidths>,
+B<-mergeweights>/B<-nomergeweights>,
+B<-mergeshapes>/B<-nomergeshapes>
 
-Some font families put their Condensed, Narrow, Extended etc. widths
-in separate families;
-this option tells B<autoinst> to merge those separate families into
+Some font put different widths, weights or shapes (e.g., small caps)
+in separate families.
+These options tell B<autoinst> to merge those separate families into
 the main family.
-The default is B<-mergewidths>.
+Since this is usually desirable, they are all enabled by default.
 
-=item B<-mergesmallcaps> / B<-nomergesmallcaps>
+In earlier versions, B<-mergeshapes> was called B<-mergesmallcaps>;
+for reasons of backward compatibility, that option is still supported.
 
-Even more annoyingly, some font families put their small caps fonts
-in a separate family;
-this option tells B<autoinst> to merge the small caps fonts into
-the main family.
-The default is B<-mergesmallcaps>.
-
 =item B<-nfssweight>=I<code>=I<weight>, B<-nfsswidth>=I<code>=I<width>
 
 Map the NFSS code I<code> to the given weight or width,
@@ -2432,20 +2639,22 @@
 overriding the built-in tables.
 Each of these options may be given multiple times,
 to override more than one NFSS code.
-Example: to map the "ul" code to the "Thin" weight, use C<-nfssweight=ul=thin>.
-To inhibit the use of the "ul" code completely, use C<-nfssweight=ul=>.
+Example: to map the "ul" code to the "Thin" weight,
+use C<-nfssweight=ul=thin>.
+To inhibit the use of the "ul" code completely,
+use C<-nfssweight=ul=>.
 
 =item B<-extra>=I<text>
 
 Append I<text> as extra options to the command lines for I<otftotfm>.
-To prevent I<text> from accidentily being interpreted as options to B<autoinst>,
-it should be properly quoted.
+To prevent I<text> from accidentily being interpreted as options
+to B<autoinst>, it should be properly quoted.
 
 =item B<-manual>
 
-Manual mode; for users who want to post-process the generated files and commands.
-By default, B<autoinst> immediately executes all F<otftotfm> commands
-it generates;
+Manual mode; for users who want to post-process the generated files
+and commands. By default, B<autoinst> immediately executes all
+F<otftotfm> commands it generates;
 in manual mode, these are instead written to a file F<autoinst.bat>.
 Furthermore it tells F<otftotfm> to generate human readable (and editable)
 F<pl/vpl> files instead of the default F<tfm/vf> ones,
@@ -2457,19 +2666,19 @@
 
 =over 2
 
-=item B<-> run F<pltotf> and F<vptovf> on the generated F<pl> and F<vf> files,
+=item - run F<pltotf> and F<vptovf> on the generated F<pl> and F<vf> files,
 to convert them to F<tfm/vf> format;
 
-=item B<-> move all generated files to a proper TEXMF tree,
+=item - move all generated files to a proper TEXMF tree,
 and, if necessary, update the filename database;
 
-=item B<-> tell TeX about the new F<map> file
+=item - tell TeX about the new F<map> file
 (usually by running C<updmap> or similar).
 
 =back
 
-Note that some options (I<-target>, I<-vendor> and I<-typeface>, I<-[no]updmap>)
-are meaningless, and hence ignored, in manual mode.
+Note that some options (I<-target>, I<-vendor> and I<-typeface>,
+I<-[no]updmap>) are meaningless, and hence ignored, in manual mode.
 
 =item B<-target>=I<DIRECTORY>
 
@@ -2482,7 +2691,8 @@
 it will print a warning message and put all files into the subdirectory
 C<./autoinst_output/> of the current directory.
 It's then up to the user to move the generated files to a better location
-and update all relevant databases (usually by calling F<texhash> and F<updmap>).
+and update all relevant databases
+(usually by calling F<texhash> and F<updmap>).
 
 =item B<-vendor>=I<VENDOR>
 
@@ -2496,7 +2706,7 @@
 Note that these options change I<only> directory names,
 not the names of any generated files.
 
-=item B<-updmap> / B<-noupdmap>
+=item B<-updmap>/B<-noupdmap>
 
 Control whether or not F<updmap> is called after the last call to F<otftotfm>.
 The default is B<-updmap>.
@@ -2513,13 +2723,14 @@
 For Windows, try ActivePerl (F<http://www.activestate.com>)
 or Strawberry Perl (F<http://strawberryperl.com>).
 
-B<XeTeX> (F<http://www.tug.org/xetex>) and B<LuaTeX> (F<http://www.luatex.org>)
+B<XeTeX> (F<http://www.tug.org/xetex>) and
+B<LuaTeX> (F<http://www.luatex.org>)
 are Unicode-aware TeX engines that can use OpenType fonts directly,
 without any (La)TeX-specific support files.
 
 The B<FontPro> project (F<https://github.com/sebschub/FontPro>)
-offers very complete LaTeX support (even for typesetting maths) for Adobe's
-Minion Pro, Myriad Pro and Cronos Pro font families.
+offers very complete LaTeX support (even for typesetting maths) for
+Adobe's Minion Pro, Myriad Pro and Cronos Pro font families.
 
 
 =head1 AUTHOR
@@ -2526,9 +2737,9 @@
 
 Marc Penninga (F<marcpenninga at gmail.com>)
 
-When sending a bug report, please give as much relevant information as possible;
-this usually includes (but may not be limited to) the log file
-(please add the I<-Verbose> command-line option, for extra info).
+When sending a bug report, please give as much relevant information as
+possible; this usually includes (but may not be limited to) the log file
+(please add the I<-verbose> command-line option, for extra info).
 If you see any error messages, please include these I<verbatim>;
 don't paraphase.
 
@@ -2558,7 +2769,7 @@
 
 =head1 VERSION
 
-This document describes B<autoinst> version 20190522.
+This document describes B<autoinst> version 20190625.
 
 
 =head1 RECENT CHANGES
@@ -2567,12 +2778,56 @@
 
 =over 12
 
+=item I<2019-06-25>
+
+=over 3
+
+=item -
+
+Added the I<-mergeweights> and I<-mergeshapes> options,
+and improved I<-mergewidths>.
+
+=item -
+
+Improved the parsing of fonts' widths and weights.
+
+=item -
+
+Improved the mapping of widths and weights to NFSS codes.
+
+=item -
+
+Changed logging code so that that results of font info parsing
+are always logged, even (especially!) when parsing fails.
+
+=item -
+
+Added a warning when installing fonts from multiple families.
+
+=item -
+
+Added simple recognition for sanserif and typewriter fonts.
+
+=item -
+
+Fixed error checking after calls to F<otfinfo>
+(B<autoinst> previously only checked whether C<fork()> was successful,
+not whether the actual call to F<otfinfo> worked).
+
+=item -
+
+Fixed a bug in the I<-inferiors> option;
+when used without a (supposedly optional) value,
+it would silently gobble the next option instead.
+
+=back
+
 =item I<2019-05-22>
 
 Added the I<mainfont> option to the generated F<sty> files.
 Prevented hyphenation for typewriter fonts
 (added C<\hyphenchar\font=-1> to the C<\DeclareFontFamily> declarations).
-Added the I<-version> option, and renamed I<-verbose> to I<-Verbose>.
+Added the I<-version> option.
 
 =item I<2019-05-17>
 
@@ -2832,7 +3087,7 @@
 some FontFont fonts, where every font is in a family of its own.
 Added the "scaled" option (including the loading of F<xkeyval>)
 to the generated style file.
-Extended the output of the I<-Verbose> option.
+Extended the output of the I<-verbose> option.
 
 =item I<2007-02-08>
 
@@ -2910,7 +3165,7 @@
 file to include an interface for the ornaments and to load Lehman's NFSS
 extensions F<nfssext.sty> if this is installed; corrected the "fontname" codes
 for OT1, T1, LY1 and user-specific encodings; extended the output generated by
-the I<-Verbose> option; and rewrote and extended the documentation.
+the I<-verbose> option; and rewrote and extended the documentation.
 
 =item I<2005-06-16>
 

Modified: trunk/Master/texmf-dist/scripts/fontools/ot2kpx
===================================================================
--- trunk/Master/texmf-dist/scripts/fontools/ot2kpx	2019-06-26 20:40:49 UTC (rev 51472)
+++ trunk/Master/texmf-dist/scripts/fontools/ot2kpx	2019-06-26 20:41:25 UTC (rev 51473)
@@ -38,7 +38,7 @@
 use List::Util @List::Util::EXPORT_OK;
 use Pod::Usage;
 
-my $VERSION = "20190522";
+my $VERSION = "20190625";
 
 our ($NUM_GLYPHS, $UNITS_PER_EM, %kern);
 
@@ -48,12 +48,12 @@
     );
 
     Getopt::Long::GetOptions(
-        'help|?'    =>  sub { pod2usage(-verbose => 0); },
-        'version'   =>  sub { print "$VERSION\n"; exit; },
-        'doc'       =>  sub { pod2usage(-verbose => 2); },
-        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx; },
-        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx; },
-        'lua'       =>  sub { $ARGV{print_func} = \&print_lua; },
+        'help|?'    =>  sub { pod2usage(-verbose => 0) },
+        'version'   =>  sub { print "$VERSION\n"; exit },
+        'doc'       =>  sub { pod2usage(-verbose => 2) },
+        'afm'       =>  sub { $ARGV{print_func} = \&print_kpx },
+        'kpx'       =>  sub { $ARGV{print_func} = \&print_kpx },
+        'lua'       =>  sub { $ARGV{print_func} = \&print_lua },
     ) or pod2usage(-verbose => 0);
     pod2usage(-verbose => 0) if @ARGV != 1;
 
@@ -100,8 +100,8 @@
 # Print kerning data in Adobe's KPX format
 # ------------------------------------------------------------------------
 sub print_kpx {
-    my %kern = %{ shift @_; };
-    my @glyph = @{ shift @_; };
+    my %kern = %{ shift @_ };
+    my @glyph = @{ shift @_ };
 
     my $num_kernpairs = sum map { scalar keys %{$kern{$_}} } keys %kern;
     print "StartKernData\nStartKernPairs $num_kernpairs\n";
@@ -119,8 +119,8 @@
 # Print kerning data as a Luatex custom font feature
 # ------------------------------------------------------------------------
 sub print_lua {
-    my %kern = %{ shift @_; };
-    my @glyph = @{ shift @_; };
+    my %kern = %{ shift @_ };
+    my @glyph = @{ shift @_ };
 
     print <<'END_FEATURE_PREFIX';
 fonts.handlers.otf.addfeature {
@@ -739,7 +739,7 @@
 
 =head1 SYNOPSIS
 
-B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<fontfile>
+B<ot2kpx> [ I<-afm> | I<-kpx> | I<-lua> ] B<< <fontfile> >>
 
 
 =head1 DESCRIPTION
@@ -771,7 +771,7 @@
 Output the kerning data as a Luatex custom font feature,
 to be included in a C<\directlua> command.
 
-=item B<fontfile>
+=item B<< <fontfile> >>
 
 The OpenType font (both F<otf> and F<ttf> format are supported).
 
@@ -858,7 +858,7 @@
 
 =head1 VERSION
 
-This document describes B<ot2kpx> version 20190522.
+This document describes B<ot2kpx> version 20190625.
 
 
 =head1 RECENT CHANGES



More information about the tex-live-commits mailing list