summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2024-05-07 20:11:51 +0000
committerKarl Berry <karl@freefriends.org>2024-05-07 20:11:51 +0000
commitab60ca3774663a7c219641b4a47296cdd2b28149 (patch)
treeffe26f05768770125971090cd4f7ea204886ce0d
parenta82447a1b9056aeb9499e8452dd8aa4f1e1c4b6b (diff)
typog (7may24)
git-svn-id: svn://tug.org/texlive/trunk@71202 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.am1
-rw-r--r--Build/source/texk/texlive/linked_scripts/Makefile.in1
-rw-r--r--Build/source/texk/texlive/linked_scripts/scripts.lst1
-rwxr-xr-xBuild/source/texk/texlive/linked_scripts/typog/typog-grep.pl614
l---------Master/bin/aarch64-linux/typog-grep1
l---------Master/bin/amd64-freebsd/typog-grep1
l---------Master/bin/amd64-netbsd/typog-grep1
l---------Master/bin/armhf-linux/typog-grep1
l---------Master/bin/i386-freebsd/typog-grep1
l---------Master/bin/i386-linux/typog-grep1
l---------Master/bin/i386-netbsd/typog-grep1
l---------Master/bin/i386-solaris/typog-grep1
l---------Master/bin/universal-darwin/typog-grep1
-rwxr-xr-xMaster/bin/windows/typog-grep.exebin0 -> 6144 bytes
l---------Master/bin/x86_64-cygwin/typog-grep1
l---------Master/bin/x86_64-darwinlegacy/typog-grep1
l---------Master/bin/x86_64-linux/typog-grep1
l---------Master/bin/x86_64-linuxmusl/typog-grep1
l---------Master/bin/x86_64-solaris/typog-grep1
-rw-r--r--Master/texmf-dist/doc/latex/typog/README.md79
-rw-r--r--Master/texmf-dist/doc/latex/typog/RELEASE-HOWTO.md51
-rw-r--r--Master/texmf-dist/doc/latex/typog/crooked-paragraphs.mp119
-rw-r--r--Master/texmf-dist/doc/latex/typog/index.md5
-rw-r--r--Master/texmf-dist/doc/latex/typog/slant-angle.mp87
-rw-r--r--Master/texmf-dist/doc/latex/typog/smooth-parshapes.mp140
-rw-r--r--Master/texmf-dist/doc/latex/typog/teximan2latex.sed55
-rw-r--r--Master/texmf-dist/doc/latex/typog/title.mp92
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog-example.pdfbin0 -> 392419 bytes
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog-example.tex1616
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog-grep.1.pdfbin0 -> 511632 bytes
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog-grep.pod345
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog-nomt.tex73
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog.ist41
-rw-r--r--Master/texmf-dist/doc/latex/typog/typog.pdfbin0 -> 902362 bytes
-rw-r--r--Master/texmf-dist/doc/man/man1/typog-grep.1428
-rw-r--r--Master/texmf-dist/doc/man/man1/typog-grep.man1.pdfbin0 -> 38115 bytes
-rwxr-xr-xMaster/texmf-dist/scripts/typog/typog-grep.pl614
-rw-r--r--Master/texmf-dist/source/latex/typog/Makefile302
-rw-r--r--Master/texmf-dist/source/latex/typog/typog.dtx9974
-rw-r--r--Master/texmf-dist/source/latex/typog/typog.ins74
-rw-r--r--Master/texmf-dist/tex/latex/typog/typog.sty1401
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rwxr-xr-xMaster/tlpkg/libexec/ctan2tds5
-rw-r--r--Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/typog.tlpsrc3
45 files changed, 16137 insertions, 1 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.am b/Build/source/texk/texlive/linked_scripts/Makefile.am
index 6483ac8d5cd..ba4e7be48fd 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.am
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.am
@@ -256,6 +256,7 @@ texmf_other_scripts = \
thumbpdf/thumbpdf.pl \
tlcockpit/tlcockpit.sh \
tlshell/tlshell.tcl \
+ typog/typog-grep.pl \
ulqda/ulqda.pl \
urlbst/urlbst \
vpe/vpe.pl \
diff --git a/Build/source/texk/texlive/linked_scripts/Makefile.in b/Build/source/texk/texlive/linked_scripts/Makefile.in
index b40c07e6229..447f6518ae1 100644
--- a/Build/source/texk/texlive/linked_scripts/Makefile.in
+++ b/Build/source/texk/texlive/linked_scripts/Makefile.in
@@ -473,6 +473,7 @@ texmf_other_scripts = \
thumbpdf/thumbpdf.pl \
tlcockpit/tlcockpit.sh \
tlshell/tlshell.tcl \
+ typog/typog-grep.pl \
ulqda/ulqda.pl \
urlbst/urlbst \
vpe/vpe.pl \
diff --git a/Build/source/texk/texlive/linked_scripts/scripts.lst b/Build/source/texk/texlive/linked_scripts/scripts.lst
index 12fa2241416..479473cdf8c 100644
--- a/Build/source/texk/texlive/linked_scripts/scripts.lst
+++ b/Build/source/texk/texlive/linked_scripts/scripts.lst
@@ -197,6 +197,7 @@ texplate/texplate.sh
thumbpdf/thumbpdf.pl
tlcockpit/tlcockpit.sh
tlshell/tlshell.tcl
+typog/typog-grep.pl
ulqda/ulqda.pl
urlbst/urlbst
vpe/vpe.pl
diff --git a/Build/source/texk/texlive/linked_scripts/typog/typog-grep.pl b/Build/source/texk/texlive/linked_scripts/typog/typog-grep.pl
new file mode 100755
index 00000000000..bc7f0e98fbd
--- /dev/null
+++ b/Build/source/texk/texlive/linked_scripts/typog/typog-grep.pl
@@ -0,0 +1,614 @@
+#! /usr/bin/env perl
+
+use autodie qw(:all);
+use strict;
+use warnings;
+
+use Data::Dumper ();
+use English;
+use File::Basename ();
+use Getopt::Long;
+use IO::File;
+use IO::Handle;
+use Term::ANSIColor ();
+
+use constant COMMAND_NAME => File::Basename::basename($PROGRAM_NAME);
+
+my $DEBUG = 0;
+my $MATCH_COUNT = 0;
+my $OUTPUT_IS_REDIRECTED;
+
+sub fail_with_error {
+ print STDERR join('', COMMAND_NAME, ': ', @_, "\n");
+ exit 2;
+}
+
+sub issue_warning {
+ print STDERR join('', COMMAND_NAME, ': warning: ', @_, "\n");
+}
+
+sub debug_print {
+ return unless $DEBUG;
+ print STDERR "+ @_\n";
+}
+
+sub quote_filesystem {qq("$_[0]")}
+sub quote_literal {qq(`$_[0]')}
+
+sub limit_string_length {
+ my ($a_string, $a_maximum_length) = @_;
+
+ if (length $a_string <= $a_maximum_length) {
+ $a_string;
+ } else {
+ substr($a_string, 0, $a_maximum_length - 3) . '...';
+ }
+}
+
+## We set all colors to `undef' and fill them later with the values
+## of the actual configuration.
+my $highlight_patterns = {
+ PARTIAL_LINE => {
+ FONT_SPEC => [qr#
+ \\
+ (?: OMS | OMX | OT1 | T1 | TS1 | U )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ #x, undef],
+ MATH => [qr#
+ \$
+ \\
+ (?: LMS | OML )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ .*?
+ \$
+ #x, undef]
+ },
+ WHOLE_LINE => {
+ FILL_STATE => [qr#^(?:Under|Over)full \\hbox .*$#, undef],
+ FIRST_VBOX => [qr#^%%#, undef],
+ HORIZONTAL_BREAKPOINT => [qr#^@@\d+:.*$#, undef],
+ HORIZONTAL_BREAK_CANDIDATE => [qr#^@[\\ ].*$#, undef],
+ LINE_BREAK_PASS => [qr#^@[a-z]+?pass#, undef],
+ TIGHTNESS => [qr#^(?:Loose|Tight) \\hbox .*$#, undef],
+ VERTICAL_BREAKPOINT => [qr#^% t=\d+.*$#, undef]
+ }
+};
+
+sub colorize_line {
+ my ($configuration, $line) = @_;
+
+ foreach my $pattern_color_pair (values %{$highlight_patterns->{WHOLE_LINE}}) {
+ next unless $pattern_color_pair->[1];
+ return Term::ANSIColor::colored($line, $pattern_color_pair->[1])
+ if $line =~ $pattern_color_pair->[0];
+ }
+ return $line if $line =~ m#^\.#; # we do not paint box contents yet
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{MATH}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{MATH}->[1])
+ #egx;
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[1])
+ #egx;
+
+ return $line;
+}
+
+my $open_or_close_tag_regexp = qr#^</?typog-inspect[ >]#; # somewhat sloppy definition
+my $close_tag_regexp = qr#^</typog-inspect>#;
+my $open_tag_regexp =
+ qr#^
+ <typog-inspect \s+
+ id="(?<id_match> .*?)" \s+
+ job="(?<job_match> .*?)" \s+
+ line="(?<line_match> .*?)" \s+
+ page="(?<page_match> .*?)"
+ >#x;
+
+sub grep_log_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $job_name;
+ my $line_number = 0; # line number in the log file we are inspecting, i.e., $filename
+ my $match_count = 0;
+ my $source_line_number; # line number in TeX file the log refers to, i.e., "$job_name.tex"
+ my $page_number;
+ my $regexp_modifier = $options->{IGNORE_CASE} ? 'i' : '';
+ my $id_value;
+ my @nesting_levels;
+
+ if ($options->{WORD_REGEXP}) {
+ $id_regexp = "\\b$id_regexp\\b";
+ }
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if (@nesting_levels and $nesting_levels[-1] and $line !~ $open_or_close_tag_regexp) {
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ if ($options->{ID} and not $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_INLINE_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id = Term::ANSIColor::colored($formatted_id ,
+ $configuration->{COLORS}->{ID_COLOR});
+ }
+ print $formatted_id, ' ';
+ }
+
+ if ($options->{COLORIZE_OUTPUT}) {
+ print colorize_line($configuration, $line);
+ } else {
+ print $line;
+ }
+ print "\n";
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ $job_name = $+{job_match};
+ $source_line_number = $+{line_match};
+ $page_number = $+{page_match};
+
+ my $found_matching_id = ($id_value =~ m/(?$regexp_modifier)$id_regexp/) ? 1 : 0;
+ push @nesting_levels, $found_matching_id;
+ if ($found_matching_id) {
+ ++$MATCH_COUNT; # global count -- needed for return code of program
+ ++$match_count; # per file count -- needed to be able to separate the hunks
+
+ print "\n" if $match_count >= 2;
+ if ($options->{ID} and $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_HEADING_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id =
+ Term::ANSIColor::colored($formatted_id,
+ $configuration->{COLORS}->{ID_HEADING_COLOR});
+ }
+ print $formatted_id, "\n";
+ }
+ }
+ }
+ }
+}
+
+sub show_ids_in_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $line_number = 0;
+ my @nesting_levels;
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ my $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ my $job_name = $+{job_match};
+ my $source_line_number = $+{line_match};
+ my $page_number = $+{page_match};
+
+ ++$MATCH_COUNT;
+ push @nesting_levels, 1;
+
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ my $indent = $configuration->{ID_INDENT} * (@nesting_levels - 1);
+ print ' ' x $indent, $id_value, "\n";
+ }
+ }
+}
+
+sub open_file_for_reading {
+ my $filename = shift;
+
+ my $file;
+
+ if ($filename eq 'stdin') {
+ $file = IO::Handle->new();
+ $file->fdopen(fileno(STDIN), 'r') or
+ fail_with_error("cannot open stdin: $OS_ERROR");
+ } else {
+ $file = IO::File->new($filename, 'r') or
+ fail_with_error("cannot open @{[quote_filesystem($filename)]}: $OS_ERROR");
+ }
+
+ $file;
+}
+
+sub close_file {
+ my ($file, $filename) = shift;
+
+ $file->close or
+ issue_warning("problems while closing @{[quote_filesystem($filename)]}: $OS_ERROR");
+}
+
+sub grep_or_show {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ if ($options->{SHOW_ALL_IDS}) {
+ show_ids_in_file($options, $configuration, $file, $filename, $id_regexp);
+ } else {
+ grep_log_file($options, $configuration, $file, $filename, $id_regexp);
+ }
+}
+
+sub scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ if (@$log_filenames) {
+ foreach my $log_filename (@$log_filenames) {
+ $log_filename = 'stdin' if $log_filename eq '-';
+ if (@$log_filenames >= 2) {
+ print "\n" unless $log_filename eq $log_filenames->[0];
+ my $filename_header = "==> $log_filename <==\n";
+ $filename_header = Term::ANSIColor::colored($filename_header,
+ $configuration->{COLORS}->{FILE_HEADER})
+ if $options->{COLORIZE_OUTPUT};
+ print $filename_header;
+ }
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+ } else {
+ my $log_filename = 'stdin';
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+}
+
+sub redirect_and_scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ my $pager;
+
+ my $pid = open($pager, '|-', $configuration->{PAGER}, $configuration->{PAGER_FLAGS});
+ fail_with_error('failed to redirect to pager ', quote_literal($configuration->{PAGER}),
+ ' with flags ', quote_literal($configuration->{PAGER_FLAGS}),
+ ": $OS_ERROR")
+ unless defined $pid;
+ my $stdout = select $pager;
+
+ $pager->autoflush;
+ scan_files($options, $configuration, $id_regexp, $log_filenames);
+
+ close $pager or issue_warning "error occurred while closing the pager (pid: $pid) pipe: $OS_ERROR";
+ select $stdout;
+}
+
+########################################################################
+
+my $configuration_key_map = {
+ 'id-format' => 'ID_INLINE_FORMAT',
+ 'id-indent' => 'ID_INDENT',
+ 'id-heading' => 'PRINT_ID_AS_HEADING',
+ 'id-heading-format' => 'ID_HEADING_FORMAT',
+ 'id-max-length' => 'ID_MAX_LENGTH',
+ 'line-number-format' => 'LINE_NUMBER_FORMAT',
+ 'log-line-number-format' => 'LOG_LINE_NUMBER_FORMAT',
+ 'page-number-format' => 'PAGE_NUMBER_FORMAT',
+
+ 'file-header-color' => 'FILE_HEADER',
+ 'fill-state-color' => 'FILL_STATE',
+ 'first-vbox-color' => 'FIRST_VBOX',
+ 'font-spec-color' => 'FONT_SPEC',
+ 'horizontal-break-candidate-color' => 'HORIZONTAL_BREAK_CANDIDATE',
+ 'horizontal-breakpoint-color' => 'HORIZONTAL_BREAKPOINT',
+ 'id-color' => 'ID_COLOR',
+ 'id-heading-color' => 'ID_HEADING_COLOR',
+ 'line-break-pass-color' => 'LINE_BREAK_PASS',
+ 'line-number-color' => 'LINE_NUMBER',
+ 'log-line-number-color' => 'LOG_LINE_NUMBER',
+ 'math-color' => 'MATH',
+ 'page-number-color' => 'PAGE_NUMBER',
+ 'pager' => 'PAGER',
+ 'pager-flags' => 'PAGER_FLAGS',
+ 'tightness-color' => 'TIGHTNESS',
+ 'vertical-breakpoint-color' => 'VERTICAL_BREAKPOINT'
+};
+
+my $default_configuration = {
+ COLORS => {
+ FILE_HEADER => 'bold black',
+ FILL_STATE => 'bold magenta',
+ FIRST_VBOX => 'bold red',
+ FONT_SPEC => 'grey12',
+ HORIZONTAL_BREAKPOINT => 'bold green',
+ HORIZONTAL_BREAK_CANDIDATE => 'blue',
+ ID_COLOR => 'white on_black',
+ ID_HEADING_COLOR => 'white on_black',
+ LINE_BREAK_PASS => 'bold green',
+ LINE_NUMBER => 'bold black',
+ LOG_LINE_NUMBER => 'italic black',
+ MATH => 'yellow',
+ PAGE_NUMBER => 'bold white on_red',
+ TIGHTNESS => 'bold cyan',
+ VERTICAL_BREAKPOINT => 'red'
+ },
+ ID_INLINE_FORMAT => '%s:',
+ ID_HEADING_FORMAT => '--> %s <--',
+ ID_INDENT => 8,
+ ID_MAX_LENGTH => 40,
+ LINE_NUMBER_FORMAT => '%5d',
+ LOG_LINE_NUMBER_FORMAT => '%6d',
+ PAGE_NUMBER_FORMAT => '[%3d]',
+ PAGER => 'less',
+ PAGER_FLAGS => '--quit-if-one-screen',
+ PRINT_ID_AS_HEADING => 0
+};
+
+sub initialize_highlighting_from_configuration {
+ my $configuration = shift;
+
+ while (my (undef, $assoc) = each %$highlight_patterns) {
+ while (my ($name, $pattern_color_pair) = each %$assoc) {
+ $pattern_color_pair->[1] = $configuration->{COLORS}->{$name};
+ }
+ }
+}
+
+sub modify_configuration {
+ my ($configuration, $key, $value) = @_;
+
+ fail_with_error('malformed KEY=VALUE pair -- missing key') unless $key;
+
+ if (defined $configuration_key_map->{$key}) {
+ if ($key =~ m/-color$/) {
+ $configuration->{COLORS}->{$configuration_key_map->{$key}} = $value;
+ } else {
+ $configuration->{$configuration_key_map->{$key}} = $value;
+ }
+ } else {
+ fail_with_error("@{[quote_literal($key)]} is not a valid configuration KEY");
+ }
+}
+
+sub setup_configuation {
+ my ($config_spec, $configuration) = @_;
+
+ foreach my $spec (split ':', $config_spec) {
+ my ($key, $value) = split '=', $spec;
+ modify_configuration($configuration, $key, $value);
+ }
+}
+
+my $default_options = {
+ COLORIZE_MODE => 'auto',
+ DEBUG => 0,
+ ID => 0,
+ IGNORE_CASE => 0,
+ JOB_NAME => 0,
+ LINE_NUMBER => 0,
+ LOG_LINE_NUMBER => 0,
+ PAGE_NUMBER => 0,
+ REQUEST_PAGER => 1,
+ WORD_REGEXP => 0
+};
+
+sub show_help {
+ print <<HELP_TEXT;
+Usage: @{[COMMAND_NAME]} [OPTION] ID-REGEXP LOG-FILE...
+Structured grep for typog-inspect elements that match ID-REGEXP in LOG-FILE.
+
+Options
+ --color [WHEN],
+ --colour [WHEN] use color to highlight specific log contents
+ WHEN is 'always', 'never', or 'auto'
+ -C, --config KEY=VALUE set configuration KEY to VALUE
+ -i, --[no-]id print matching id with output lines
+ -y, --[no-]ignore-case ignore case distinctions in patterns and data
+ -j, --[no-]job-name print \\jobname with output lines
+ -n, --[no-]line-number print TeX-source line number with output lines
+ -N, --[no-]log-line-number print log-file line number with output lines
+ -p, --[no-]page-number print page number with output lines
+ -P, --[no-]pager redirect output to pager
+ -w, --[no-]word-regexp match only whole words
+
+ -a, --all, --any show all IDs in LOG-FILE
+ --debug turn on debug output
+ -h, --help display this help and exit
+ --show-config show default configuration and exit
+ -V, --version show version information and exit
+
+HELP_TEXT
+
+ exit 0;
+}
+
+sub show_configuration {
+ my $format_string_value = sub {quote_literal($default_configuration->{$_[0]})};
+
+ print <<FIXED_CONFIGURATION_TEXT;
+Configuration
+Key Default Value
+------------------------------------ -------------
+id-format @{[$format_string_value->('ID_INLINE_FORMAT')]}
+id-heading $default_configuration->{PRINT_ID_AS_HEADING}
+id-heading-format @{[$format_string_value->('ID_HEADING_FORMAT')]}
+id-indent $default_configuration->{ID_INDENT}
+id-max-length $default_configuration->{ID_MAX_LENGTH}
+line-number-format @{[$format_string_value->('LINE_NUMBER_FORMAT')]}
+log-line-number-format @{[$format_string_value->('LOG_LINE_NUMBER_FORMAT')]}
+page-number-format @{[$format_string_value->('PAGE_NUMBER_FORMAT')]}
+pager @{[$format_string_value->('PAGER')]}
+pager-flags @{[$format_string_value->('PAGER_FLAGS')]}
+
+FIXED_CONFIGURATION_TEXT
+
+ foreach my $configuration_key (sort keys %$configuration_key_map) {
+ next unless $configuration_key =~ m/-color$/;
+ printf("%-36s %s\n",
+ $configuration_key,
+ quote_literal($default_configuration->
+ {COLORS}->
+ {$configuration_key_map->{$configuration_key}}));
+ }
+
+ exit 0;
+}
+
+sub show_version {
+ print <<VERSION_TEXT;
+typog-grep 0.1
+
+Copyright (C) 2024 by Ch. L. Spiel
+License LPPL: LaTeX Project Public License version 1.3 or later
+VERSION_TEXT
+
+ exit 0;
+}
+
+sub get_options {
+ my ($options, $configuration) = @_;
+
+ Getopt::Long::Configure('gnu_getopt', 'no_ignore_case');
+
+ Getopt::Long::GetOptions('a|all|any' => \$options->{SHOW_ALL_IDS},
+ 'color|colour=s' => \$options->{COLORIZE_MODE},
+ 'C|configuration=s' => sub{setup_configuation($_[1], $configuration)},
+ 'debug+' => \$DEBUG,
+ 'h|help' => \&show_help,
+ 'i|id!' => \$options->{ID},
+ 'y|ignore-case!' => \$options->{IGNORE_CASE},
+ 'j|job-name!' => \$options->{JOB_NAME},
+ 'n|line-number!' => \$options->{LINE_NUMBER},
+ 'N|log-line-number!' => \$options->{LOG_LINE_NUMBER},
+ 'p|page-number!' => \$options->{PAGE_NUMBER},
+ 'P|pager!' => \$options->{REQUEST_PAGER},
+ 'show-config' => \&show_configuration,
+ 'V|version' => \&show_version,
+ 'w|word-regexp!' => \$options->{WORD_REGEXP}) or
+ fail_with_error('problems while parsing options');
+
+ fail_with_error("unknown colorize mode @{[quote_literal($options->{COLORIZE_MODE})]}")
+ unless $options->{COLORIZE_MODE} =~ m/^(?:always|auto|never)$/i
+}
+
+sub do_colorize {
+ my $colorize_mode = shift;
+
+ if ($colorize_mode =~ m/never/i) {
+ 0;
+ } elsif ($colorize_mode =~ m/always/i) {
+ 1;
+ } elsif ($colorize_mode =~ m/auto/i) {
+ not $OUTPUT_IS_REDIRECTED;
+ }
+}
+
+## For the comparison with the POSIX spec of grep(1) consult
+## https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
+
+sub main {
+ $OUTPUT_IS_REDIRECTED = -t STDOUT ? 0 : 1;
+
+ my $options = {%$default_options};
+ my $configuration = {%$default_configuration};
+
+ get_options($options, $configuration);
+ $options->{COLORIZE_OUTPUT} = do_colorize($options->{COLORIZE_MODE});
+ initialize_highlighting_from_configuration($configuration);
+ debug_print(Data::Dumper::Dumper($configuration));
+ debug_print(Data::Dumper::Dumper($options));
+
+ my $id_regexp;
+ if ($options->{SHOW_ALL_IDS}) {
+ $id_regexp = '^';
+ issue_warning("option @{[quote_literal('--id')]} ignored in @{[quote_literal('--all')]} mode")
+ if $options->{ID};
+ } else {
+ fail_with_error('missing ID-REGEXP') unless @ARGV >= 1;
+ $id_regexp = shift @ARGV;
+ }
+
+ if ($options->{REQUEST_PAGER} && $OUTPUT_IS_REDIRECTED) {
+ issue_warning("option @{[quote_literal('--pager')]} ignored because output is redirected");
+ }
+ my $use_pager = $options->{REQUEST_PAGER} && !$OUTPUT_IS_REDIRECTED;
+ if ($use_pager) {
+ redirect_and_scan_files($options, $configuration, $id_regexp, \@ARGV);
+ } else {
+ scan_files($options, $configuration, $id_regexp, \@ARGV);
+ }
+
+ exit ($MATCH_COUNT == 0);
+}
+
+main();
diff --git a/Master/bin/aarch64-linux/typog-grep b/Master/bin/aarch64-linux/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/aarch64-linux/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/amd64-freebsd/typog-grep b/Master/bin/amd64-freebsd/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/amd64-freebsd/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/amd64-netbsd/typog-grep b/Master/bin/amd64-netbsd/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/amd64-netbsd/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/armhf-linux/typog-grep b/Master/bin/armhf-linux/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/armhf-linux/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/i386-freebsd/typog-grep b/Master/bin/i386-freebsd/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/i386-freebsd/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/i386-linux/typog-grep b/Master/bin/i386-linux/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/i386-linux/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/i386-netbsd/typog-grep b/Master/bin/i386-netbsd/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/i386-netbsd/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/i386-solaris/typog-grep b/Master/bin/i386-solaris/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/i386-solaris/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/universal-darwin/typog-grep b/Master/bin/universal-darwin/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/universal-darwin/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/windows/typog-grep.exe b/Master/bin/windows/typog-grep.exe
new file mode 100755
index 00000000000..3332231b08c
--- /dev/null
+++ b/Master/bin/windows/typog-grep.exe
Binary files differ
diff --git a/Master/bin/x86_64-cygwin/typog-grep b/Master/bin/x86_64-cygwin/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/x86_64-cygwin/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-darwinlegacy/typog-grep b/Master/bin/x86_64-darwinlegacy/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/x86_64-darwinlegacy/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-linux/typog-grep b/Master/bin/x86_64-linux/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/x86_64-linux/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-linuxmusl/typog-grep b/Master/bin/x86_64-linuxmusl/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/x86_64-linuxmusl/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/bin/x86_64-solaris/typog-grep b/Master/bin/x86_64-solaris/typog-grep
new file mode 120000
index 00000000000..74d1a6a5621
--- /dev/null
+++ b/Master/bin/x86_64-solaris/typog-grep
@@ -0,0 +1 @@
+../../texmf-dist/scripts/typog/typog-grep.pl \ No newline at end of file
diff --git a/Master/texmf-dist/doc/latex/typog/README.md b/Master/texmf-dist/doc/latex/typog/README.md
new file mode 100644
index 00000000000..fb55ccb1e12
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/README.md
@@ -0,0 +1,79 @@
+# TypoG &ndash; Typographic Fine-Tuning for LaTeX
+
+LaTeX package `typog` provides macros for (micro-)typographic enhancements;
+it covers a variety of topics:
+
+* Precise hyphenation control
+* Disable/break ligatures
+* Manual italic correction
+* Extra kerning for slash and hyphen
+* Raising selected characters (e.g. hyphen, en-dash, and em-dash)
+* Aligning of the last line of a paragraph
+* Filling of the last line last line of a paragraph
+* Word spacing control
+* [Microtype](https://github.com/schlcht/microtype) front-end
+* Slightly sloppy paragraphs
+* Vertically partially-tied paragraphs
+* Breakable displayed equations
+* Setspace front-end
+* Smooth ragged-right paragraphs
+
+Moreover `typog` provides an environment to flag interesting parts of
+the information deluge typically accumulating in a LaTeX *log*-file
+and an associated tool, **typog-grep**, that selectively retrieves
+these parts.
+
+
+## Installation
+
+The minimally necessary files to install typog are *typog.ins* and *typog.dtx*. Running LaTeX
+on *typog.ins* in particular produces *typog.sty*:
+
+ latex typog.ins
+
+After extraction from *typog.dtx* place *typog.sty* in a directory mentioned in your TEXINPUTS
+paths or copy it into one of the directories for your LaTeX installation's *sty*-files and run
+**mktexlsr** or equivalent.
+
+To build the documentation it is easier to use the GNU *Makefile*:
+
+ make
+
+To construct the manual *typog.pdf* or the usage example *typog-example.pdf* a working
+[MetaPost](https://tug.org/metapost.html) installation and some
+[POD](https://perldoc.perl.org/perlpod) utilities of a [Perl](https://www.perl.org/)
+distribution are required. Cautious users can run
+
+ make tool-check
+
+ahead to verify that the required utilities are installed and working.
+For an overview over the most important *Makefile* targets use
+
+ make help
+
+
+## Usage
+
+Load the package with the usual incantation
+
+ \usepackage{typog}
+
+See Section 2 of the package documentation for available options.
+
+
+## Documentation
+
+The package documentation can be found
+[online](https://cspiel.github.io/typog/).
+
+
+## Credits
+
+Typog is written by Ch. L. Spiel <cspiel@users.sourceforge.org>.
+
+
+## License
+
+Released under the
+[LaTeX Project Public License v1.3c](https://www.latex-project.org/lppl.txt)
+or later.
diff --git a/Master/texmf-dist/doc/latex/typog/RELEASE-HOWTO.md b/Master/texmf-dist/doc/latex/typog/RELEASE-HOWTO.md
new file mode 100644
index 00000000000..13435ef66d5
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/RELEASE-HOWTO.md
@@ -0,0 +1,51 @@
+# How to prepare a new release
+
+... and not make too many mistakes.
+
+
+1. Check that the work-area is clean with respect to **git**-tracked
+ files.
+
+ ``` git status ```
+
+1. Update the date stamp of `\ProvidesPackage`.
+
+1. (Temporarily) Zero the `\overfullrule`s of the documentation and
+ the example files.
+
+1. Thoroughly clean the work-area:
+
+ ```make maintainer-clean```
+
+1. Rebuild:
+
+ ```make```
+
+1. Check that all _*.sty_ and _*.pdf_ files are in good shape.
+
+1. Push the documentation files created in the previous step down into
+ the *docs* directory:
+
+ ```make update-docs```
+
+1. Undo the `\overfullrule` change.
+
+1. Commit the changes:
+
+ ```
+ git add .
+ ```
+
+ and finally
+
+ ```
+ git commit
+ ```
+
+1. Tag the commit with the version string of `\ProvidesPackage`:
+
+ ```git tag v1.23```
+
+1. Push the changes to the public repository:
+
+ ```git push origin master --tags```
diff --git a/Master/texmf-dist/doc/latex/typog/crooked-paragraphs.mp b/Master/texmf-dist/doc/latex/typog/crooked-paragraphs.mp
new file mode 100644
index 00000000000..778a3bc3846
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/crooked-paragraphs.mp
@@ -0,0 +1,119 @@
+%%
+%% This is file `crooked-paragraphs.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `crookedparagraphs')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+prologues := 3;
+
+def draw_filled_rectangle(expr lower_left, upper_right, color) =
+ fill lower_left -- (xpart upper_right, ypart lower_left) --
+ upper_right -- (xpart lower_left, ypart upper_right) --
+ cycle
+ withcolor color;
+enddef;
+
+u := 100;
+
+em := 10;
+linelength := 2u;
+baselineskip := 1.2em;
+parskip := 3;
+parindent := 2.5em;
+
+cmykcolor line_color;
+line_color := (.08, 0, 0, .18); % cold silver
+
+color customred[];
+customred[1] := (.890, .282, .282);
+customred[2] := (.831, .110, .110);
+customred[3] := (.686, .043, .043);
+customred[4] := (.569, .000, .000);
+customred[5] := (.420, .000, .000);
+
+color margin_color;
+margin_color := customred[2];
+
+beginfig(1); % short line -- gap
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (1.1em, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((parindent, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip), margin_color);
+endfig;
+
+beginfig(2); % short line -- covered
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (2parindent, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((parindent, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip), margin_color);
+endfig;
+
+beginfig(3); % completely filled line -- no clear paragraph break
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip - parskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip - parskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip - parskip),
+ margin_color);
+endfig;
+
+beginfig(4); % completely filled line -- opened right margin
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - parindent, y + 1em), line_color);
+ y := y - baselineskip - parskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip - parskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip - parskip),
+ margin_color);
+endfig;
+end
diff --git a/Master/texmf-dist/doc/latex/typog/index.md b/Master/texmf-dist/doc/latex/typog/index.md
new file mode 100644
index 00000000000..f4dc2e8bd9a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/index.md
@@ -0,0 +1,5 @@
+### Package Documentation
+
+- Comprehensive `typog` documentation: [typog.pdf](https://cspiel.github.io/typog/typog.pdf)
+- `typog` examples and tests: [typog-example.pdf](https://cspiel.github.io/typog/typog-example.pdf)
+- **typog-grep** manual page: [typog-grep.1](https://cspiel.github.io/typog/typog-grep.1) and as PDF: [typog-grep.1.pdf](https://cspiel.github.io/typog/typog-grep.1.pdf)
diff --git a/Master/texmf-dist/doc/latex/typog/slant-angle.mp b/Master/texmf-dist/doc/latex/typog/slant-angle.mp
new file mode 100644
index 00000000000..f25f790ea6f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/slant-angle.mp
@@ -0,0 +1,87 @@
+%%
+%% This is file `slant-angle.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `slantangle')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+prologues := 3;
+truecorners := 1;
+linecap := butt;
+
+input TEX;
+TEXPRE("%&latex" & char(10) & "\documentclass{article}\begin{document}");
+TEXPOST("\end{document}");
+
+string roman_font;
+roman_font := "pplr8r"; % URW Palladio L - Roman
+
+string italics_font;
+italics_font := "pplri8r"; % URW Palladio L - Italic
+
+u := 360;
+
+font_scale := 10;
+
+pair loc[];
+loc[1] := .2[origin, (u, 0)];
+loc[2] := .5[origin, (u, 0)];
+loc[3] := .8[origin, (u, 0)];
+
+picture letter_H;
+letter_H := thelabel.top("H" infont italics_font scaled font_scale, loc[1]);
+
+picture letter_L;
+letter_L := thelabel.top("L" infont italics_font scaled font_scale, loc[2]);
+
+picture letter_a;
+letter_a := thelabel.top("a" infont italics_font scaled font_scale, loc[3]);
+
+path slant_angle;
+slant_angle := lrcorner letter_H + (14, 0) -- lrcorner letter_H + (-6, 0) -- urcorner letter_H + (3.5, 0);
+
+pair base_point;
+base_point := (xpart point 2 of slant_angle, ypart point 0 of slant_angle) ;
+
+pair angle_label;
+angle_label := point 2 of slant_angle + (0, -12);
+
+beginfig(1);
+ draw letter_H;
+ draw slant_angle;
+ draw point 2 of slant_angle -- base_point dashed evenly;
+ draw point 1 of slant_angle -- base_point withpen pencircle scaled 2pt;
+
+ label.rt(TEX("$\alpha$"), angle_label);
+
+ draw letter_L;
+ draw slant_angle shifted (xpart lrcorner letter_L - xpart lrcorner letter_H + 2, 0);
+
+ draw letter_a;
+ draw slant_angle shifted (xpart lrcorner letter_a - xpart lrcorner letter_H - 3, 0);
+endfig;
+end
diff --git a/Master/texmf-dist/doc/latex/typog/smooth-parshapes.mp b/Master/texmf-dist/doc/latex/typog/smooth-parshapes.mp
new file mode 100644
index 00000000000..ce47135a56e
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/smooth-parshapes.mp
@@ -0,0 +1,140 @@
+%%
+%% This is file `smooth-parshapes.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `smoothparshapes')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+prologues := 3;
+
+def draw_filled_rectangle(expr lower_left, upper_right, color) =
+ fill lower_left -- (xpart upper_right, ypart lower_left) --
+ upper_right -- (xpart lower_left, ypart upper_right) --
+ cycle
+ withcolor color;
+enddef;
+
+u := 100;
+
+em := 10;
+linelength := 2u;
+baselineskip := 1.2em;
+parskip := 3;
+parindent := 2.5em;
+ragwidth := 2em;
+
+cmykcolor line_color;
+line_color := (.08, 0, 0, .18); % cold silver
+
+color customred[];
+customred[1] := (.890, .282, .282);
+customred[2] := (.831, .110, .110);
+customred[3] := (.686, .043, .043);
+customred[4] := (.569, .000, .000);
+customred[5] := (.420, .000, .000);
+
+color margin_color;
+margin_color := customred[2];
+
+beginfig(1); % triplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth/2, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth/2, y + 1em), line_color); % (2)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -5baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -5baselineskip), margin_color);
+endfig;
+
+beginfig(2); % quintuplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - .75ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .25ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .75ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .25ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -9baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -9baselineskip), margin_color);
+endfig;
+
+beginfig(3); % septuplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - .6667ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .1667ragwidth, y + 1em), line_color); % (6)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .3333ragwidth, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .8333ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (7)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .6667ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .1667ragwidth, y + 1em), line_color); % (6)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .3333ragwidth, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .8333ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (7)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (4)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -13baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -13baselineskip), margin_color);
+endfig;
+end
diff --git a/Master/texmf-dist/doc/latex/typog/teximan2latex.sed b/Master/texmf-dist/doc/latex/typog/teximan2latex.sed
new file mode 100644
index 00000000000..b329ac3845f
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/teximan2latex.sed
@@ -0,0 +1,55 @@
+## Remove all lines we neither need nor want.
+/^\\input /d
+/^@anchor/d
+/^@bye/d
+/^@documentencoding/d
+/^@node/d
+/^@setfilename/d
+/^@settitle/d
+/^@top/d
+/@menu/,/@end menu/d
+
+## Convert sectioning macros to our own hierarchy.
+s/^@chapter \(.*\)$/\\subsection*{\\textls[40]{\1}}/
+s/^@section \(.*\)$/\\subsubsection*{\1}/
+
+## Make `@asis' list resemble the Texinfo format.
+s/@table @asis/\\begin{list}{}{\\itemindent=-20pt\\leftmargin=20pt}/
+s/@end table/\\end{list}/
+
+## Indenting by four spaces generates a `verbatim' environment.
+s/@verbatim/\\begin{verbatim}/
+s/@end verbatim/\\end{verbatim}/
+
+## We substitute @display for our maxipage environment.
+s/@display/\\begin{maxipage}/
+s/@end display/\\end{maxipage}/
+
+## The argument format of the URL macro is different.
+s/@url{\([^,]*\), \([^}]*\)}/\\href{\1}{\2}/g
+
+## Use our own markup.
+s/\.\.\./\\dots{}/g
+s/LaTeX/\\LaTeX{}/g
+s/@file/\\textit/g
+s/@strong/\\textbf/g
+s/[w]{/mbox{/g
+
+## Quote some special characters.
+s/%/\\%/g
+s/_/\\_/g
+
+## Adapt to how a man-page is typeset.
+## En-dashes in front of long options really suck!
+s/--/-\\nolig*-/g
+
+## Converting the at-signs to backslashes is a bit tricky.
+s/^@item/\\item/
+s/@\([A-Za-z][A-Za-z]*\){/\\\1{/g
+s/@@/@/g
+
+## Convert selected macro names.
+s/\\jobname/\\textbackslash jobname/g
+
+## Make qualified Perl names breakable.
+s/::/::\\discretionary{}{}{}/g
diff --git a/Master/texmf-dist/doc/latex/typog/title.mp b/Master/texmf-dist/doc/latex/typog/title.mp
new file mode 100644
index 00000000000..2fd74e91f9d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/title.mp
@@ -0,0 +1,92 @@
+%%
+%% This is file `title.mp',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `title')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+prologues := 3;
+truecorners := 1;
+linecap := butt;
+
+string roman_font;
+roman_font := "pplr8r"; % URW Palladio L - Roman
+
+string italics_font;
+italics_font := "pplri8r"; % URW Palladio L - Italic
+
+picture dash_dotted;
+dash_dotted := dashpattern(on 3 off 3 on 0 off 3);
+
+u := 280;
+
+font_scale := 20;
+
+pair loc[];
+loc[1] := .2[origin, (u, 0)];
+loc[2] := .5[origin, (u, 0)];
+loc[3] := .8[origin, (u, 0)];
+
+pair slant_vector;
+slant_vector := (63, 150);
+
+pair raise_vector[];
+raise_vector[0] := (0, 44);
+raise_vector[1] := (0, 61);
+raise_vector[2] := (0, 54);
+raise_vector[3] := (0, 71);
+
+picture letter_V;
+letter_V := thelabel.top("V" infont roman_font scaled font_scale, loc[1]);
+
+picture normal_hyphen;
+normal_hyphen := thelabel.top("-" infont roman_font scaled font_scale, loc[2] + raise_vector[0]);
+
+picture raised_hyphen;
+raised_hyphen := thelabel.top("-" infont roman_font scaled font_scale, loc[2] + raise_vector[1]);
+
+picture letter_A;
+letter_A := thelabel.top("A" infont roman_font scaled font_scale, loc[3]);
+
+beginfig(1);
+ draw letter_V;
+ draw normal_hyphen withcolor .9 white;
+ draw raised_hyphen;
+ draw letter_A;
+
+ pickup pencircle scaled .4pt;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (7, 0) dashed evenly;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (27, 0) dashed evenly;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (80, 0) dashed evenly;
+ draw (loc[3] -- loc[3] + slant_vector) shifted (-68, 0) dashed evenly;
+
+ draw .35[origin, (u, 0)] + raise_vector[2] -- .8[origin, (u, 0)] + raise_vector[2]
+ dashed dash_dotted withcolor .6white;
+ draw .35[origin, (u, 0)] + raise_vector[3] -- .8[origin, (u, 0)] + raise_vector[3]
+ dashed dash_dotted;
+endfig;
+end
diff --git a/Master/texmf-dist/doc/latex/typog/typog-example.pdf b/Master/texmf-dist/doc/latex/typog/typog-example.pdf
new file mode 100644
index 00000000000..621ac319d20
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog-example.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/typog/typog-example.tex b/Master/texmf-dist/doc/latex/typog/typog-example.tex
new file mode 100644
index 00000000000..af04d490094
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog-example.tex
@@ -0,0 +1,1616 @@
+%%
+%% This is file `typog-example.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `example')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+\documentclass[a4paper]{article}
+
+\tracingonline=0
+
+\PassOptionsToPackage{dvipsnames}{xcolor}
+
+\usepackage{amsmath}
+\usepackage[main=USenglish, german]{babel}
+\usepackage{float}
+\usepackage[T1]{fontenc}
+\usepackage{fullwidth}
+\usepackage{hyphenat}
+\usepackage{mathtools}
+\usepackage[activate=true, verbose=true]{microtype}
+\usepackage{ragged2e}
+\usepackage[nobottomtitles*]{titlesec}\renewcommand*{\bottomtitlespace}{.2\textheight}
+\usepackage[debug, trackingttspacing]{typog}
+\usepackage{xcolor}
+
+\usepackage[loosest, proportional, scaled=1.064]{erewhon}
+\usepackage[erewhon]{newtxmath}
+\usepackage[scaled=.95]{cabin}
+\usepackage{inconsolata}
+\usepackage{setspace}\setstretch{1.08333}
+
+\def\xsfdefault{\relax}
+{
+ \def\examplefont{6}
+
+ \ifcase\examplefont % 0 -- document's default sans-serif font (e.g., ecrm1000)
+ \gdef\examplefontname{default}
+ \global\let\xsf=\sf
+ \global\let\xsfdefault=\sfdefault
+ \or % 1 -- Nunito
+ \gdef\examplefontname{Nunito}
+ \usepackage{nunito}
+ \xdef\xsfdefault{\rmdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 2 -- OpenSans
+ \gdef\examplefontname{OpenSans}
+ \usepackage[defaultsans]{opensans}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 3 -- Noto Sans
+ \gdef\examplefontname{OpenSans}
+ \usepackage[sfdefault]{noto}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 4 -- Roboto
+ \gdef\examplefontname{Roboto}
+ \usepackage[sfdefault]{roboto}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 5 -- Montserrat
+ \gdef\examplefontname{Montserrat Alternate}
+ \usepackage[alternates]{montserrat}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 6 -- Inter
+ \gdef\examplefontname{Inter}
+ \usepackage[sfdefault]{inter}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \else
+ \SelectedUnknownExampleFont
+ \fi
+
+ \typeout{typog-example: font for examples: `\xsfdefault'}%
+}
+
+\usepackage{hyperref}
+\usepackage{cleveref}
+
+\hypersetup{
+ citecolor = CadetBlue,
+ colorlinks = true,
+ linkcolor = Blue,
+ linktocpage = true,
+ pdfauthor={Dr. Christoph L. Spiel},
+ pdfkeywords={Examples,
+ LaTeX, typography, ligature, italic-correction, paragraph justification, sloppy, ragged},
+ pdfsubject={Examples for typographic fine-tuning of LaTeX},
+ pdftitle={Examples for LaTeX package typog},
+ raiselinks = false,
+ urlcolor = Mulberry
+}
+
+\makeatletter
+\newcommand{\fs@myruled}{%
+ \fs@ruled
+ \def\@fs@capt##1##2{\floatc@ruled{##1\space\capitaldash*\space}{\fussy ##2}}%
+ \def\@fs@pre{\hrule height.8pt depth0pt \kern4pt}%
+ \def\@fs@mid{\kern3pt\hrule\kern3pt}%
+ \def\@fs@post{\kern4pt\hrule\relax}%
+}
+\makeatother
+
+\floatstyle{myruled}
+\newfloat{exemplary}{htbp}{loe}[section]
+\floatname{exemplary}{Example}
+\Crefname{exemplary}{Example}{Examples}
+\crefname{exemplary}{Ex.}{Ex.}
+
+\newcommand*{\acronym}[1]{\mbox{\letterspacecapitals{\MakeUppercase{#1}}}}
+\newcommand*{\bibauthor}[1]{\textsc{#1}}
+\newcommand*{\bibtitle}[1]{\textit{#1}}
+\newcommand*{\bottomstrut}{\rule[-.5em]{0pt}{0pt}}
+\newcommand*{\code}[1]{{\ttfamily\hyphenchar\font=`\-\relax #1}}
+\newcommand*{\doublequotes}[1]{\doubleguillemetright#1\doubleguillemetleft}
+\newcommand*{\eTeX}{\mbox{\(\epsilon\)-\TeX}}
+\newcommand*{\letterspacecapitals}[1]{\textls[30]{#1}}
+\newcommand*{\metavar}[1]{\textit{#1}}
+\newcommand*{\packagename}[1]{\mbox{\textsf{#1}}}
+\newcommand*{\propername}[1]{\mbox{\textsc{\textls[25]{#1}}}}
+\newcommand*{\sample}[1]{\mbox{`\texttt{#1}'}}
+\newcommand*{\singlequotes}[1]{\singleguillemetright#1\singleguillemetleft}
+\newcommand*{\topstrut}{\rule{0pt}{1.25em}}
+\newcommand*{\visualpar}{\,\P\quad}
+
+\newlength{\emreference}
+\AtBeginDocument{\setlength{\emreference}{\fontdimen6\font}}
+\newrobustcmd*{\milliem}[1]
+ {\ifdim #1=0pt
+ #1%
+ \else
+ \generictextfraction{\the\numexpr\dimexpr (#1) * 1000 / \emreference}{1000}\:em%
+ \fi}
+
+\newcommand*{\generictextfraction}[2]
+ {\raisebox{.4em}[0pt]{\scriptsize #1}%
+ \kern-.05em\textfractionsolidus\kern-.05em
+ \raisebox{-.15em}[0pt][0pt]{\scriptsize #2}}
+
+\newcommand*{\leftmarker}{\rule{.2em}{.1pt}\rule{.1pt}{.667em}}
+\newcommand*{\rightmarker}{\rule{.1pt}{.667em}\rule{.2em}{.1pt}}
+\newcommand*{\indicatewidth}[1]{\mbox{\leftmarker #1\rightmarker}}
+
+\newcommand*{\maxipagerule}{\medskip\hrule\medskip}
+\newenvironment*{maxipage*}
+ {\par
+ \noindent
+ \fullwidthsetup{leftmargin=-\marginparsep - \marginparwidth,
+ width=\textwidth + 2\marginparsep + 2\marginparwidth}
+ \begin{fullwidth}%
+ \vspace*{1pt}% Why is some vspace necessary?
+ \parskip=.5\baselineskip}
+ {\par
+ \end{fullwidth}%
+ \par}
+\newenvironment*{maxipage}
+ {\par
+ \noindent
+ \fullwidthsetup{leftmargin=-\marginparsep - \marginparwidth,
+ width=\textwidth + 2\marginparsep + 2\marginparwidth}
+ \begin{fullwidth}%
+ \maxipagerule
+ \parskip=.5\baselineskip}
+ {\par
+ \vskip\parskip
+ \maxipagerule
+ \end{fullwidth}%
+ \par}
+
+\newlength{\examplewidth}
+\setlength{\examplewidth}{160pt}
+
+\newcommand*{\texbooktolerancesample}
+ {If you want to avoid overfull boxes at all costs without trying to fix them manually,
+ you might be tempt\-ed to set \texttt{tol\-er\-ance=\allowbreak10000}; this allows
+ arbitrarily bad lines to be acceptable in tough situations. But infinite tolerance
+ is a bad idea, because \TeX{} doesn't distinguish between terribly bad and
+ preposterously horrible lines. Indeed, a tolerance of 10000 encourages \TeX{} to
+ concentrate all the badness in one place, making one truly unsightly line instead of
+ two moderately bad ones, because a single ``write-off'' produces fewest total
+ demerits according to the rules.}
+ %There is a much better way to get the desired effect:~[\dots]
+\newcommand*{\texbooktolerancesamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~107]{knuth:1986}.}}
+
+\newcommand*{\texbookparfillskipsample}
+ {We still haven't discussed the special trick that allows the final line of a paragraph
+ to be shorter than the others. Just before \TeX{} begins to choose breakpoints,
+ it does two important things: [\dots]}
+\newcommand*{\texbooklongparfillskipsample}
+ {We still haven't discussed the special trick that allows the final line of a paragraph
+ to be shorter than the others. Just before \TeX{} begins to choose breakpoints,
+ it does two important things: (1)~If the final item of the current horizontal list is glue,
+ that glue is discarded. (The reason is that a blank space often gets into a token list just
+ before \code{\char92par} or just before \code{\char36\char36}, and this blank space should not be
+ part of the paragraph.) (2)~Three or more items are put at the end of the
+ current horizontal list~[\dots]}
+\newcommand*{\texbookparfillskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~99n]{knuth:1986}.}}
+
+\newcommand*{\texbookparshapeskipsample}
+ {It's possible to control the length of lines in a much more general way, if simple
+ changes to \code{\string\leftskip} and \code{\string\rightskip} aren't flexible enough for your
+ purposes. For example, a semicircular hole has been cut out of the present paragraph,
+ in order to make room for a circular illustration that contains some of
+ Galileo's immortal words about circles; all of the line breaks in this
+ paragraph and in the circular quotation were found by \TeX's line-breaking algorithm.
+ You can specify a essentially arbitrary paragraph shape, by saying
+ \code{parshape}=\metavar{number}, where the \metavar{number} is a positive integer~\(n\),
+ followed by \(2n\)~\metavar{dimen} specifications.}
+\newcommand*{\texbookparshapeskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~101]{knuth:1986}.}}
+
+\newcommand*{\texbookbaselineskipsample}
+ {When you are typsetting a document that spans several pages, it's generally best to
+ define \code{\string\baselineskip} so that it cannot stretch or shrink, because
+ this will give more uniformity to the pages. A small variation in the distance
+ between the baselines---say only half a point---can make a substantial difference
+ in the appearance of the type, since it significantly affects the proportion of
+ white to black. On the other hand, if you are preparing a one-page document, you
+ might want to give the baselineskip some stretchability, so that \TeX{} will help
+ you fit the copy on the page.}
+\newcommand*{\texbookbaselineskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~78]{knuth:1986}.}}
+
+\newcommand*{\examplepreset}{\microtypesetup{activate=false}}
+\newcommand*{\examplesetup}{\frenchspacing\xsf\small\fussy}
+\newcommand*{\exampleparbox}[2][n/a]
+ {\begin{typoginspect}{#1}
+ \examplepreset
+ \parbox[t]{\examplewidth}{\examplesetup #2}%
+ \end{typoginspect}}
+\newcommand*{\examplesep}{\hspace*{20pt}}
+\def\fontnameandweightinfo#1{%
+ {\def\projectoutfontname##1-##2-##3\relax{##1~\lowercase{##2}}%
+ \global\expandafter\edef\csname#1\endcsname{\expandafter\projectoutfontname\fontname\font\relax}}}
+\newcommand*{\examplefontinformation}
+ {\smallskip
+ \examplesetup
+ \fontnameandweightinfo{exfontnameinfo}%
+ \fontsizeinfo{exfontsizeinfo}%
+ The font used in this example is \exfontnameinfo, \exfontsizeinfo*.}
+
+\setcounter{tocdepth}{1}
+\setlength{\overfullrule}{3pt}
+\hbadness=-1
+
+\input{ushyphex}
+
+\hyphenation{
+ Double-guillemet-left
+ Double-guillemet-right
+ Double-quotes
+ Single-guillemet-left
+ Single-guillemet-right
+ Single-quotes
+ adj-demerits
+ allow-display-breaks
+ babel-hyphenation
+ base-line-skip
+ break-penalty
+ breakable-display
+ capital-hyphen
+ capital-times
+ cite-dash
+ club-penalties
+ cref-range-conjunction
+ display-break
+ display-widow-penalties
+ double-guillemet-right
+ double-hyphen-demerits
+ double-quotes
+ final-hyphen-demerits
+ inter-display-line-penalty
+ inter-text
+ kerned-hyphen
+ last-line-ragged-left
+ last-line-ragged-left-par
+ line-width
+ loose-ness
+ loose-spacing
+ make-at-letter
+ make-at-other
+ mar-gin-al
+ math-italics-correction
+ micro-type
+ number-dash
+ par-box
+ par-indent
+ parfillskip
+ pdf-string-def-Disable-Commands
+ post-display-penalty
+ pre-display-penalty
+ raise-capital-guillemets
+ raise-capital-times
+ raise-number-dash
+ set-font-expand
+ set-font-shrink
+ set-font-stretch
+ short-inter-text
+ single-guillemet-left
+ single-guillemet-right
+ single-quotes
+ slash-kern
+ slightly-sloppy-par
+ sloppy-par
+ smooth-ragged-right-fuzz-factor
+ smooth-ragged-right-par
+ smooth-ragged-right-shape-quintuplet
+ smooth-ragged-right-shape-septuplet
+ smooth-ragged-right-shape-triplet
+ space-skip
+ text-italics-correction
+ tight-spacing
+ tracing-boxes
+ tracing-para-graphs
+ vtie-bot
+ vtie-bot-disp
+ vtie-bot-disp-par
+ vtie-bot-disp-top-par
+ vtie-bot-par
+ vtie-top
+ vtie-top-par
+ widow-penalties
+}
+
+\SetExpansion[context=sloppy, stretch=30, shrink=60, step=5]{encoding={OT1, T1, TS1}}{}% p15
+\SetTracking{encoding=*, shape=sc}{20}
+
+\begin{document}
+\fussy
+\lastlinefit=1000
+\nonfrenchspacing
+
+\begin{center}
+ \Huge\bf\sf
+ TypoG Examples
+\end{center}
+
+\bigskip
+
+\noindent
+The section numbers correspond to the subsections of section~3
+in the official documentation of package~\packagename{typog}.
+
+\bigskip
+
+\tableofcontents
+
+\clearpage
+\listof{exemplary}{Examples}
+
+\clearpage
+\noindent
+Unless otherwise noted the font used in the examples is \singlequotes{\examplefontname}.
+
+\bigskip
+
+\section{Information}
+
+\code{\string\fontsizeinfo} --\fontsizeinfo{docsizeinfo}
+At this point of the document, the font~size
+and the line~spacing are \docsizeinfo*~(w/o~units).
+For footnotes however, the current sizes are%
+\footnote{This is the footnote where we get the sizes from.\fontsizeinfo{footsizeinfo}}
+\footsizeinfo.
+
+Next we show a comparison of different font sizes and line spacings
+decorated with the results of \code{\string\fontsizeinfo}.
+
+\medskip
+
+\begin{maxipage}
+ \setstretch{1}
+ \newcommand*{\baselineskipdoc}%
+ {Macro \code{\string\baselineskip} is a length command which
+ specifies the minimum space between the bottom of two
+ successive lines in a paragraph. Its value may be
+ automatically reset by \LaTeX, for example, by font
+ changes in the text.}
+ \renewcommand*{\examplefontname}{Merriweather}
+ Different font sizes and line spacings exemplified with the \examplefontname~font.
+
+ \smallskip
+
+ \begingroup
+ \fontfamily{Merriwthr-TLF}\selectfont
+ \noindent
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{8.5}{12}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfotight}}
+ \hfill
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{10}{12}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfo}}
+ \hfill
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{10}{13.5}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfoloose}}
+ \endgroup
+
+ \medskip
+
+ \noindent
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfotight*}
+ \hfill
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfo*}
+ \hfill
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfoloose*}
+\end{maxipage}
+
+\noindent Starred form eats spaces? \examplesizeinfo* .
+
+\section{Hyphenation}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\mbox+\string\breakpoint*} \\
+ \mbox{(pre-)}\breakpoint*Hilbert space}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \code{\string\breakpoint*} \\
+ (pre-)\breakpoint*Hilbert space}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \code{\string\breakpoint} \\
+ (pre-)\breakpoint Hilbert space}
+\end{quote}
+
+\noindent Starred form eats spaces? a\breakpoint* b. Unstarred: a\breakpoint b.
+
+\medskip
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \begin{hyphenmin}{6}
+ Set minimum hyphenation values for both \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin}: \the\lefthyphenmin{} and \the\righthyphenmin.
+ \end{hyphenmin}}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \begin{hyphenmin}[4]{5}
+ Set minimum hyphenation values for \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin} separately: \the\lefthyphenmin{} and \the\righthyphenmin.
+ \end{hyphenmin}}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ Returned to the default values for \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin}: \the\lefthyphenmin{} and \the\righthyphenmin.}
+\end{quote}
+
+\section{Disable\kernedslash*Break Ligatures}
+
+\begin{center}
+ \begin{tabular}{@{}ll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Macro} & Result \\
+ \hline
+ n/a &
+ fine affirmation of baffling flavors \\
+ \code{\string\nolig*} &
+ f\nolig*ine af\nolig*f\nolig*irmation of baf\nolig*f\nolig*ling f\nolig*lavors \\
+ \code{\string\nolig} &
+ f\nolig{}ine af\nolig{}f\nolig{}irmation of baf\nolig{}f\nolig{}ling f\nolig{}lavors \\
+ \code{\string\nolig*[75]} & of\nolig*[75]f\nolig*[75]ice
+ \end{tabular}
+\end{center}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\nolig*} \\
+ bi\nolig*{}jection}
+ \hspace{60pt}
+ \parbox[t]{0pt}{%
+ \code{\string\nolig} \\
+ bi\nolig{}jection}
+\end{quote}
+
+\noindent Starred form eats spaces? f\nolig* i, f\nolig*[0] i.
+
+\section{Manual Italic Correction}
+
+\paragraph{Text Mode.}
+
+The italic correction of the current font is \the\fontdimen1\font/pt.
+
+We demonstrate the effect of \code{\string\itcorr} with a pair of bookends:
+uncorrected italics: \indicatewidth{\it X},
+\TeX-corrected (\code{\string\/}): \indicatewidth{\it X\/},
+and \code{\string\itcorr\{7\}}: \indicatewidth{\it X\itcorr{7}}.
+
+Correction~0: \indicatewidth{\itcorr*{0}};
+corr.~3: \indicatewidth{\itcorr{3}}, \indicatewidth{\itcorr*{3}} (starred);
+corr.~\textminus6: \indicatewidth{\itcorr{-6}}.
+
+\paragraph{Mathematical Mode.}
+
+Uncorrected: \([f]\),
+corrected: \([\itcorr{1} f\itcorr{1}]\)
+
+Correction~0: \indicatewidth{\(\itcorr{0}\)};
+corr.~3: \indicatewidth{\(\itcorr{3}\)};
+corr.~\textminus6: \indicatewidth{\(\itcorr{-6}\)}.
+
+\section{Apply Extra Kerning}
+
+\subsection{Slash}
+
+The slash with some extra space around it can be helpful for certain pairs,
+as for example years or names.
+
+\begin{center}
+ \begin{tabular}{@{}ll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Macro} & Result \\
+ \hline
+ n/a & 1991/1992,
+ New~York/NY, Korringa/Kohn/Rostoker \\
+ \code{\string\kernedslash} &
+ 1991\kernedslash1992, New~York\kernedslash{}NY, Korringa\kernedslash{}Kohn\kernedslash{}Rostoker \\
+ \end{tabular}
+\end{center}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash*} \\
+ 1991\kernedslash*1992,
+ New~York\kernedslash*NY,
+ Korringa\kernedslash*Kohn\kernedslash*Rostoker}
+ \hspace{120pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash} \\
+ 1991\kernedslash{}1992,
+ New~York\kernedslash{}NY,
+ Korringa\kernedslash{}Kohn\kernedslash{}Rostoker}
+\end{quote}
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash*}\code{\string\nobreak} \\
+ 1991\kernedslash*\nobreak{}1992,
+ New~York\kernedslash*\nobreak{}NY,
+ Korringa\kernedslash*Kohn\kernedslash*\nobreak{}Rostoker}
+ \hspace{140pt}
+ \parbox[t]{0pt}{%
+ \code{\string\allowhyphenation\string\kernedslash} \\
+ 1991\kernedslash{}1992,
+ New~York\kernedslash{}NY,
+ Korringa\allowhyphenation\kernedslash{}Kohn\kernedslash{}Rostoker}
+\end{quote}
+
+\noindent Starred form eats spaces? p\kernedslash* q.
+
+\subsection{Hyphen}
+
+Uncorrected
+
+\begin{quote}
+ \(K\)-vector space, \(g\)-factor, \(f\)-function
+\end{quote}
+
+\noindent Corrected
+
+\begin{quote}
+ \typogsetup{raisecapitalhyphen=.075em, raiseguillemets=.05em}
+ \(K\)\leftkernedhyphen{-75}vector space,
+ \(g\)\leftkernedhyphen{-25}factor,
+ \(f\)\leftkernedhyphen{-100}function
+ %% \(G\)\kernedhyphen[*]{50}{-50}Wirkung,
+ %% \(G\)\leftkernedhyphen{50}äquivalent,
+ %% \(K\)\kernedhyphen[*]{-50}{-50}Vektorraum,
+ %% \(K\)\kernedhyphen{-50}{-25}bilinear,
+ %% \propername{Young}\rightkernedhyphen{-50}Tableaux,
+ %% \singlequotes{Bra}\kernedhyphen[50]{50}{-50}Vektor,
+ %% \singlequotes{Ket}\kernedhyphen[50]{50}{-50}Vektor,
+ %% halbzahlige~\(l\)\kernedhyphen{50}{-50}Werte.
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+
+ \parbox[t]{0pt}{hyphen~\mbox{`\code{-}'} \\ self-energy}
+ \hspace{80pt}
+ \parbox[t]{0pt}{\code{\string\hyp} \\ self\hyp{}energy}
+ \hspace{60pt}
+ \parbox[t]{0pt}{\code{\string\kernedhyphen*} \\ self\kernedhyphen*{5}{-5}energy}
+ \hspace{80pt}
+ \parbox[t]{0pt}{\code{\string\kernedhyphen} \\ self\kernedhyphen{5}{-5}energy}
+\end{quote}
+
+\noindent If a \code{\string\kernedhyphen} goes astray in a math environment,
+it decays to an ordinary minus with appropriate kerning:
+\(G \kernedhyphen{-30}{-50} V\)\!.
+
+\section{Raise Selected Characters}
+
+\subsection{Capital Hyphen}
+
+\newlength{\exemplaryraisecapitalhyphen}
+\setlength{\exemplaryraisecapitalhyphen}{.6667pt}
+With the standard hyphen we get
+
+\begin{quote}
+ \begin{otherlanguage}{german}
+ \acronym{NMR}-Spektroskopie,
+ \acronym{SI}-Einheit,
+ \(G\)-Modul, and
+ \(K\)-Vektorraum,
+ \end{otherlanguage}
+\end{quote}
+
+\noindent whereas with raising the hyphen by \the\exemplaryraisecapitalhyphen{}
+when calling \code{\string\capitalhyphen}, we arrive at
+
+\begin{quote}
+ \begin{otherlanguage}{german}
+ \typogsetup{raisecapitalhyphen=.075em}
+
+ \acronym{NMR}\capitalhyphen{}Spektroskopie,
+ \acronym{SI}\capitalhyphen{}Einheit,
+ \(G\)\capitalhyphen{}Modul, and
+ \(K\)\capitalhyphen{}Vektorraum
+ (even better with \code{\string\kernedhyphen}
+ and the star-option for the correct raise-amount:
+ \(K\)\leftkernedhyphen[*]{-100}Vektorraum).
+ \end{otherlanguage}
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \begin{otherlanguage}{german}
+ \parbox[t]{0pt}{%
+ \code{\string\capitalhyphen*} \\
+ \acronym{NMR}\capitalhyphen*{}Spektroskopie
+ }
+ \hspace{120pt}
+ \parbox[t]{0pt}{%
+ \code{\string\capitalhyphen} \\
+ \acronym{NMR}\capitalhyphen{}Spektroskopie
+ }
+ \end{otherlanguage}
+\end{quote}
+
+\noindent Starred form eats spaces?
+{\typogsetup{raisecapitalhyphen=.075em}
+ V\capitalhyphen* W.}
+
+\subsection{Capital Dash}
+
+\newlength{\exemplaryraisecapitaldash}
+\setlength{\exemplaryraisecapitaldash}{.075em}
+
+Compare the result of plain~\code{\string\textendash}
+
+\begin{quote}
+ A\textendash M, N\textendash Z, C1\,\textendash\,C4, LEED\:\textendash\:STM
+\end{quote}
+
+\noindent with \code{\string\capitaldash}:
+
+\begin{quote}
+ \typogsetup{raisecapitaldash=\exemplaryraisecapitaldash}
+
+ A\capitaldash{}M, N\capitaldash{}Z, C1\,\capitaldash\,C4, LEED\:\capitaldash\:STM
+\end{quote}
+
+\noindent where the en-dash has been raised by \milliem{\exemplaryraisecapitaldash}.
+
+Starred form eats spaces? V\capitaldash* W.
+
+\subsection{Number Dash}
+
+\newlength{\exemplaryraisefiguredash}
+\setlength{\exemplaryraisefiguredash}{.6667pt}
+Compare the result of plain~\code{\string\textendash}
+
+\begin{quote}
+ 3--5, 81--82, 485--491
+\end{quote}
+
+\noindent with \code{\string\figuredash}:
+
+\begin{quote}
+ \typogsetup{raisefiguredash=\exemplaryraisefiguredash}
+ 3\figuredash 5, 81\figuredash 82, 485\figuredash 491
+\end{quote}
+
+\noindent where the en-dash has been raised by \the\exemplaryraisefiguredash.
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \typogsetup{raisefiguredash=\exemplaryraisefiguredash}
+ \parbox[t]{0pt}{%
+ \code{\string\figuredash*} \\
+ 3\figuredash*5, 81\figuredash*82, 485\figuredash*491
+ }
+ \hspace{80pt}
+ \parbox[t]{0pt}{%
+ \code{\string\figuredash} \\
+ 3\figuredash 5, 81\figuredash 82, 485\figuredash 491
+ }
+\end{quote}
+
+\noindent Starred form eats spaces? 44\figuredash* 55.
+
+\subsection{Multiplication Sign \capitaldash{} Times~``\texttimes''}
+
+\newlength{\exemplaryraisetimes}
+\setlength{\exemplaryraisetimes}{.6667pt}
+The problem with a too-low multiplication sign arises
+for example with matrices of a given, specific size.
+
+\noindent Uncorrected
+
+\begin{quote}
+ \acronym{LR}-mode: 2\texttimes2-matrix, \(N\)\texttimes\(M\)-matrix \\
+ Math-mode: \(2\times2\)-matrix, \(N\times M\)-matrix
+\end{quote}
+
+\noindent and corrected
+
+\begin{quote}
+ \typogsetup{raisecapitalhyphen=\exemplaryraisecapitalhyphen,
+ raisecapitaltimes=\exemplaryraisetimes}
+ \acronym{LR}-mode: 2\capitaltimes2-matrix, \(N\)\capitaltimes\(M\)-matrix \\
+ Math-mode: \(2\capitaltimes2\)-matrix, \(N\capitaltimes M\)-matrix.
+\end{quote}
+
+\subsection{Guillemets}
+
+\newcommand*{\tschicholdi}
+ {Use single quotes for a first quotation.}
+\newcommand*{\tschicholdii}
+ {Use double quotes for quotations within quotations.}
+
+\newcommand*{\frenchsinglequotes}[1]{\singleguillemetright #1\singleguillemetleft}
+\newcommand*{\Frenchsinglequotes}[1]{\Singleguillemetright #1\Singleguillemetleft}
+\newcommand*{\frenchdoublequotes}[1]{\doubleguillemetright #1\doubleguillemetleft}
+\newcommand*{\Frenchdoublequotes}[1]{\Doubleguillemetright #1\Doubleguillemetleft}
+
+\newcommand*{\frenchsinglequotesFR}[1]{\singleguillemetleft\,\allowhyphenation#1\,\singleguillemetright}
+\newcommand*{\FrenchsinglequotesFR}[1]{\Singleguillemetleft\,\allowhyphenation#1\,\Singleguillemetright}
+\newcommand*{\frenchdoublequotesFR}[1]{\doubleguillemetleft\,\allowhyphenation#1\,\doubleguillemetright}
+\newcommand*{\FrenchdoublequotesFR}[1]{\Doubleguillemetleft\,\allowhyphenation#1\,\Doubleguillemetright}
+
+\newlength{\exemplaryraiseguillemets}
+\setlength{\exemplaryraiseguillemets}{.05em}
+\newlength{\exemplaryraisecapitalguillemets}
+\setlength{\exemplaryraisecapitalguillemets}{.1em}
+
+We again compare the default implementation with the adjusted one.
+
+\begin{quote}
+ \frenchsinglequotes{\tschicholdi} \\
+ \frenchdoublequotes{\tschicholdii} \\
+ \Frenchsinglequotes{1}, \Frenchsinglequotes{2}, \Frenchsinglequotes{3}. \\
+ \Frenchdoublequotes{\letterspacecapitals{ABC}},
+ \Frenchdoublequotes{\letterspacecapitals{MN}},
+ \Frenchdoublequotes{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent Corrected by raising the glyphs by
+\milliem{\exemplaryraiseguillemets} and
+\milliem{\exemplaryraisecapitalguillemets}, respectively:
+
+\begin{quote}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+ \frenchsinglequotes{\tschicholdi} \\
+ \frenchdoublequotes{\tschicholdii} \\
+ \Frenchsinglequotes{1}, \Frenchsinglequotes{2}, \Frenchsinglequotes{3}. \\
+ \Frenchdoublequotes{\letterspacecapitals{ABC}},
+ \Frenchdoublequotes{\letterspacecapitals{MN}},
+ \Frenchdoublequotes{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent And the same using French typographic conventions:
+
+\begin{quote}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+ \frenchsinglequotesFR{\tschicholdi} \\
+ \frenchdoublequotesFR{\tschicholdii} \\
+ \FrenchsinglequotesFR{1}, \FrenchsinglequotesFR{2}, \FrenchsinglequotesFR{3}. \\
+ \FrenchdoublequotesFR{\letterspacecapitals{ABC}},
+ \FrenchdoublequotesFR{\letterspacecapitals{MN}},
+ \FrenchdoublequotesFR{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+
+ \newcommand*{\samplestring}{relation}
+
+ \parbox[t]{0pt}{\frenchsinglequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\Frenchsinglequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\frenchdoublequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\Frenchdoublequotes{\samplestring}}
+
+ \smallskip
+
+ \parbox[t]{0pt}{\frenchsinglequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\FrenchsinglequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\frenchdoublequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\FrenchdoublequotesFR{\samplestring}}
+\end{quote}
+
+\clearpage
+\section{Align Last Line}
+
+\subsection{Last Line Ragged Left/Flush Right}
+
+\Cref{ex:lastlineraggedleftpar} is a typical use of environment~\code{lastlineraggedleftpar}:
+A narrow paragraph gets typeset with full justification
+and put \code{\string\flushright} against the right margin as a whole.
+
+The layout may look more coherent if the last lines is moved to the right margin, too.
+
+\begin{exemplary}
+ \flushright
+ \caption[Justified -- flushright]
+ {\begin{typoginspectpar}{justified-flushright}Typeset a justified paragraph flushright and let
+ macro~\code{\string\lastlineraggedleft} shift the last line
+ over to the right-hand side.\label{ex:lastlineraggedleftpar}\end{typoginspectpar}}
+
+ \setlength{\examplewidth}{220pt}
+ \exampleparbox[lastlineraggedleftpar]{\lastlineraggedleftpar\texbookparfillskipsample}
+
+ \centering
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\subsection{Last Line Centered}
+
+The situation shown in \cref{ex:lastlinecenteredpar} is
+more widespread than \cref{ex:lastlineraggedleftpar}
+because centered tables and figures are quite common.
+Their caption parboxes are centered too,
+which is where a centered last line might fortify the layout.
+
+Another possible use of environment~\code{lastlinecenteredpar} are the final lines of chapters~--
+in particular if the chapters' ends are marked with centered dingbats.
+
+\begin{exemplary}
+ \centering
+ \caption[Typeset a justified paragraph that is centered.]
+ {\lastlinecenteredpar
+ Typeset a justified paragraph that is centered.
+ This very caption uses \code{lastlinecenteredpar}
+ to have its last line centered as well.
+ Moreover, we put a nifty asterisk centered at the bottom of the sample text.
+ \label{ex:lastlinecenteredpar}}
+
+ \setlength{\examplewidth}{220pt}
+ \exampleparbox[lastlinecenteredpar]{\lastlinecenteredpar\texbookparfillskipsample}
+
+ \medskip\(\ast\)
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\clearpage
+\section{Fill Last Line}
+
+\newcommand*{\abcsample}{abcd efgh ijkl mnop qrst uvwx yz12 3456}
+
+\begin{exemplary}
+ \def\sness{2}
+ \def\exparindent{25pt}
+ \setlength{\examplewidth}{235pt}
+
+ \centering
+ \caption[Plain paragraph vs.~\code{covernextindentpar}]
+ {Top example: Typeset a paragraph without correction of the last line.
+ Middle example: Paragraph corrected with \code{covernextindentpar}.
+ We set a \code{\string\parindent} of~\exparindent{} in both parboxes
+ and we \emph{must} increase the amount of glue in the paragraph
+ to reduce the penalty of stretching the last line under a \code{\string\fussy}~setting.
+ For the samples below, we have chosen \code{\string\slightlysloppy[\sness]}.
+ The \singlequotes{Alternative}, the bottom example,
+ shows the effect of \code{tightspacing};
+ no extra sloppyness is required there.}
+
+ \exampleparbox[covernextindentpar-reference]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[covernextindentpar]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \covernextindentpar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ Alternative\dots\hfill\smallskip
+
+ \exampleparbox[covernextindentpar-tightspacing]{%
+ \setlength{\parindent}{\exparindent}%
+ \begin{tightspacing}
+ \texbookparfillskipsample{} \abcsample
+ \end{tightspacing}}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \def\sness{2}
+ \def\exparindent{0pt}
+ \setlength{\examplewidth}{155pt}
+
+ \centering
+ \caption[Plain paragraph vs.~\code{covernextindentpar} (narrow)]
+ {Same comparison as the previous example,
+ but for a small linewidth and zippo~\code{\string\parindent}.
+ The left-hand side sample is uncorrected,
+ the right-hand side features \code{\string\covernextindentpar}.
+ The sloppyness level is~\sness{} for both samples.}
+
+ \exampleparbox[narrow-covernextindentpar-reference]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \texbookparfillskipsample{} \abcsample}
+ \qquad
+ \exampleparbox[narrow-covernextindentpar]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \covernextindentpar[30pt]
+ \texbookparfillskipsample{} \abcsample}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \def\exparindent{10pt}
+ \setlength{\examplewidth}{233pt}
+
+ \centering
+ \caption[Prevent full last line]
+ {Sample~1: Typeset a paragraph without correction of the last line.
+ Sample~2: Paragraph corrected with \code{\string\openlastlinepar}.~-- Disappointing!
+ Sample~3: Same using macro~\code{\string\prolongpar}.
+ Sample~4: Alternative solution that simply increases the tracking by
+ \generictextfraction{2}{1000}\,em with~\code{setfonttracking}.
+ Sample~5: Alternative solution that increases the spacing with
+ \code{loosespacing}.}
+
+ \exampleparbox[openline-reference]{%
+ \setlength{\parindent}{\exparindent}
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[openlastlinepar]{%
+ \setlength{\parindent}{\exparindent}
+ \openlastlinepar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[prolongpar]{%
+ \setlength{\parindent}{\exparindent}
+ \prolongpar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ Alternatives\dots\hfill\smallskip
+
+ \exampleparbox[openline-tracking]{%
+ \setlength{\parindent}{\exparindent}%
+ \setfonttracking{2}
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[openline-spacing]{%
+ \setlength{\parindent}{\exparindent}%
+ \begin{loosespacing}
+ \texbookparfillskipsample{} \abcsample
+ \end{loosespacing}}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\clearpage
+\section{Spacing}
+
+\subsection{Narrow\kernedslash Wide Space}
+
+The current font's parameters are shown in \cref{tab:fontdim}.\footnote{For a concise and
+understandable explanation of the plethora of font parameters
+consult \propername{David Carlisle's} excellent post on \propername{StackExchange}:
+\href{https://tex.stackexchange.com/questions/88991/what-do-different-fontdimennum-mean}%
+ {What Do Different Fontdimennum Mean}.}
+
+\begin{table}[htp]
+ \centering
+ \caption{Important \code{\string\fontdimen} values of the current text font.
+ The middle column~(\#) states the number of the fontdimen.\bottomstrut}
+ \label{tab:fontdim}
+
+ \begin{tabular}{@{}lll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Name} & \multicolumn{1}{l|}{\#} & Value \\
+ \hline
+ Interword space & 2 & \the\fontdimen2\font\topstrut \\
+ Interword stretch & 3 & \the\fontdimen3\font \\
+ Interword shrink & 4 & \the\fontdimen4\font \\
+ Extra space & 7 & \the\fontdimen7\font
+ \end{tabular}
+\end{table}
+
+\begin{center}
+ \setlength{\overfullrule}{0pt}
+ \newcommand*{\spacesampletext}[1]{some#1text#1with#1spaces\rule{0.1pt}{1em}}
+ \newsavebox{\narrowspacesample}
+ \sbox{\narrowspacesample}{\spacesampletext{\narrowspace}}
+ \newsavebox{\widespacesample}
+ \sbox{\widespacesample}{\spacesampletext{\widespace}}
+
+ \begin{tabular}{@{}ll@{\qquad}l@{}}
+ Compare & \spacesampletext{\space} & default space, natural glue \\
+ with & \usebox{\narrowspacesample} & \code{\string\narrowspace}, natural glue \\
+ {} & \makebox[\wd\narrowspacesample][l]{\hbox to 0pt{\spacesampletext{\narrowspace}}} &
+ \code{\string\narrowspace}, tight box \\
+ {} & \makebox[\wd\narrowspacesample][l]{\hbox spread 5pt{\spacesampletext{\narrowspace}}} &
+ \code{\string\narrowspace}, spread 5pt \\
+ and again & \spacesampletext{\space} & default space, natural glue \\
+ with & \usebox{\widespacesample} & \code{\string\widespace}, natural glue \\
+ {} & \makebox[\wd\widespacesample][l]{\hbox to 0pt{\spacesampletext{\widespace}}} &
+ \code{\string\widespace}, tight box \\
+ {} & \makebox[\wd\widespacesample][l]{\hbox spread 5pt{\spacesampletext{\widespace}}} &
+ \code{\string\widespace}, spread 5pt
+ \end{tabular}
+\end{center}
+
+\noindent Starred form eats spaces? Narrow\narrowspace* Space. Wide\widespace* Space.
+
+\subsection{Looser\kernedslash*Tighter}
+
+\Cref{ex:spacing-i,ex:spacing-ii} show \code{tightspacing} and \code{loosespacing} at work.
+
+\begin{exemplary}
+ \newcommand*{\sness}{3}
+ \newcommand*{\tlevel}{1}
+ \centering
+
+ \caption[Looser or tighter spacing -- sloppy]
+ {Both parboxes are typeset with \code{\string\slightlysloppy[\sness]},
+ the left one with default spacing,
+ the right one with \code{tightspacing[\tlevel]}.\label{ex:spacing-i}}
+
+ \exampleparbox[tightspacing-reference]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[tightspacing]{\slightlysloppy[\sness]\tightspacing[\tlevel]\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \newcommand*{\sness}{3}
+ \newcommand*{\llevel}{2}
+ \centering
+
+ \caption[Looser or tighter spacing -- sloppy]
+ {Both parboxes are typeset with \code{\string\slightlysloppy[\sness]},
+ the left one with default spacing,
+ the right one with \code{loosespacing[\llevel]}.\label{ex:spacing-ii}}
+
+ \exampleparbox[loosespacing-reference]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[loosespacing]{\slightlysloppy[\sness]\loosespacing[\llevel]\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\clearpage
+\section{Microtype Front\capitalhyphen End}
+
+\subsection{Tracking}
+
+\newcommand*{\trackingsampletext}{%
+ This sentence contains an explicit call to \code{\string\textls}
+ with an optional argument of \((+200)\) to \textls[200]{DEMONSTRATE}
+ that this macro still works inside of \code{setfonttracking}.
+ Apart from that it is just some more text to exercise the macro.
+ Well, the explicit letterspacing example is particularly ugly.}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \def\extratracking{7}
+ \centering
+
+ \caption[Microtype: tracking]
+ {Use \packagename{microtype} to change the font tracking.
+ The sample on the left-hand side shows neutral tracking.
+ The one on the right-hand side received an extra tracking of
+ \generictextfraction{\extratracking}{1000}\,em.}
+
+ \exampleparbox[microtype-tracking-reference]{%
+ \fussy
+ \noindent
+ \trackingsampletext}
+ \qquad
+ \exampleparbox[microtype-tracking-stretch]{%
+ \begin{setfonttracking}{\extratracking}
+ \fussy
+ \noindent
+ \trackingsampletext
+ \end{setfonttracking}}
+
+ \examplefontinformation
+\end{exemplary}
+
+\newcommand*{\trackingsamplefontchangetext}{%
+ {\rm RM} {\sf SF} {\rm RM} {\tt TT} {\rm RM};
+ {\rm RM} {\it IT\/} {\rm RM};
+ {\rm RM} {\sc SC} {\rm RM}.
+ {\rm Rm} {\sf Sf} {\rm Rm} {\tt Tt} {\rm Rm};
+ {\rm Rm} {\it It\/} {\rm Rm};
+ {\rm Rm} {\sc Sc} {\rm Rm}.
+ {\rm rm} {\sf sf} {\rm rm} {\tt tt} {\rm rm};
+ {\rm rm} {\it it\/} {\rm rm};
+ {\rm rm} {\sc sc} {\rm rm}.}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \def\extratracking{1}
+ \centering
+
+ \caption[Microtype: tracking -- font changes]
+ {Check how font changes (serif, serif~italics, small-caps, sans~serif, typewriter)
+ interfere with the interword spacing.
+ The left sample has no tracking changes applied and serves as a reference,
+ whereas the right sample got an extra tracking of
+ \generictextfraction{\extratracking}{1000}\,em.\visualpar
+ The switch from and to typewriter, i.\,e., constant-width fonts
+ commonly is a source of spacing problems.}
+
+ \exampleparbox[microtype-tracking-font-changes-reference]{\trackingsamplefontchangetext}
+ \qquad
+ \exampleparbox[microtype-tracking-font-changes-stretch]{%
+ \begin{setfonttracking}{\extratracking}
+ \trackingsamplefontchangetext
+ \end{setfonttracking}}
+\end{exemplary}
+
+\noindent
+No contents: \leftmarker
+\begin{setfonttracking}{0}
+\end{setfonttracking}\rightmarker.
+
+\subsection{Font Expansion}
+
+\newcommand*{\expansionsample}
+ {By default, all characters of a font are allowed to be stretched or
+ shrunk by the same amount. However, it is also possible to limit
+ the expansion of certain characters if they are more sensitive to
+ deformation.
+ This is the purpose of the \code{\string\SetExpansion}~command.}
+
+\begin{exemplary}
+ \setlength{\examplewidth}{250pt}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \renewcommand*{\examplesetup}{\frenchspacing\small\fussy}
+
+ \centering
+
+ \caption[Microtype: font expansion]
+ {Use \packagename{microtype} to stretch or shrink a font.
+ The top sample uses \code{\string\setfontshrink} at level~3,
+ the middle sample is the unchanged reference
+ (which is allowed to shrink and expand),
+ and the bottom sample utilizes \code{\string\setfontstretch} at level~2.}
+
+ \exampleparbox[microtype-expansion-shrink]{%
+ \begin{setfontshrink}[3]
+ \noindent\expansionsample
+ \end{setfontshrink}}
+
+ \medskip
+
+ \exampleparbox[microtype-expansion-neutral]{%
+ \begin{setfontexpand}[0]
+ \noindent\expansionsample
+ \end{setfontexpand}}
+
+ \medskip
+
+ \exampleparbox[microtype-expansion-stretch]{%
+ \begin{setfontstretch}[2]
+ \noindent\expansionsample
+ \end{setfontstretch}}
+
+ \examplefontinformation
+\end{exemplary}
+
+\noindent
+No contents -- \code{setfontshrink}: \leftmarker
+\begin{setfontshrink}
+\end{setfontshrink}\rightmarker.
+
+\noindent
+No contents -- \code{setfontstretch}: \leftmarker
+\begin{setfontstretch}
+\end{setfontstretch}\rightmarker.
+
+\noindent
+No contents -- \code{setfontexpand}: \leftmarker
+\begin{setfontexpand}
+\end{setfontexpand}\rightmarker.
+
+\noindent
+No contents -- \code{nofontexpansion}: \leftmarker
+\begin{nofontexpansion}
+\end{nofontexpansion}\rightmarker.
+
+\subsection{Character Protrusion}
+
+\newcommand*{\zerodepthrule}
+ {\raisebox{0pt}[0pt][0pt]{\rule[-4.5\baselineskip]{.1pt}{4.25\baselineskip}}}
+
+\newcommand*{\protrusionsampletext}{%
+ \noindent
+ \zerodepthrule\hfill\zerodepthrule \\
+ 1\hfill 1 \\
+ .2\hfill 2. \\
+ --3\hfill 3-- \\
+ ---4\hfill 4---}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \renewcommand*{\examplesetup}{\frenchspacing\small\fussy}
+
+ \centering
+
+ \caption[Microtype: protrusion]
+ {Comparison of the \packagename{microtype} feature ``protrusion'' (left-hand side)
+ and \code{nocharprotrusion} (right-hand side).}
+
+ \exampleparbox[microtype-protrusion-reference]{%
+ \microtypesetup{protrusion=true}
+ \protrusionsampletext}
+ \qquad
+ \exampleparbox[microtype-protrusion-off]{%
+ \microtypesetup{protrusion=true}
+ \nocharprotrusion
+ \protrusionsampletext}
+
+ \medskip
+\end{exemplary}
+
+\noindent
+No contents -- \code{nocharprotrusion}: \leftmarker
+\begin{nocharprotrusion}
+\end{nocharprotrusion}\rightmarker.
+
+\clearpage
+\section{Sloppy Paragraphs}
+
+\Cref{ex:slightlysloppy-1,ex:slightlysloppy-2} put different amounts of ``sloppiness'' face to face.
+
+\begin{exemplary}
+ \setlength{\examplewidth}{180pt}
+ \def\sness{1}
+ \centering
+ \caption[Paragraphs typeset slightly sloppy~1]
+ {Paragraphs typeset slightly sloppy: \code{\string\slightlysloppy} vs.~\code{\string\fussy}.
+ The left parbox is typeset with \code{\string\slightlysloppy}
+ and \(\metavar{sloppiness} = \sness\), whereas the right sample
+ features the well known \code{\string\fussy} setting.
+ Both parboxes have a width of \the\examplewidth.\label{ex:slightlysloppy-1}}
+
+ \exampleparbox[fussy-vs-slightlysloppy]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[fussy-vs-slightlysloppy-reference]{\fussy\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \setlength{\examplewidth}{150pt}
+ \def\sness{2}
+ \centering
+ \caption[Paragraphs typeset slightly sloppy~2]
+ {Paragraphs typeset slightly sloppy: \code{\string\slightlysloppy} vs.~\code{\string\sloppy}.
+ The left sample is features \code{\string\slightlysloppy} with \(\metavar{sloppiness} = \sness\),
+ the right sample is typeset with \code{\string\sloppy}.
+ Both parboxes have a width of \the\examplewidth.\label{ex:slightlysloppy-2}}
+
+ \exampleparbox[sloppy-vs-slightlysloppy]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[sloppy-vs-slightlysloppy-reference]{\sloppy\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+In conclusion all renderings of the text in
+\cref{ex:slightlysloppy-1} and \cref{ex:slightlysloppy-2}
+have their merits and their own flaws.
+
+\clearpage
+\section{Vertically Partially-Tied Paragraphs}
+
+\paragraph{\code{vtietoppar}}\leavevmode\par
+
+\begin{typoginspect}{vtietoppar}
+ \clubpenalty=150
+ \begin{vtietoppar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\clubpenalty} after
+ the first line of a paragraph.\footnote{Footnote of \code{vtietoppar}.}
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \end{vtietoppar}
+\end{typoginspect}
+
+\paragraph{\code{vtiebotpar}}\leavevmode\par
+
+\begin{typoginspect}{vtiebotpar}
+ \widowpenalty=150
+ \begin{vtiebotpar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\widowpenalty}
+ before the last line of the paragraph.\marginpar{A float!}
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \end{vtiebotpar}
+\end{typoginspect}
+
+\paragraph{\code{vtiebotdisp}}\leavevmode\par
+
+\begin{typoginspect}[tracingboxes]{vtiebotdisp}
+ \displaywidowpenalty=150
+ \begin{vtiebotdisp}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\displaywidowpenalty}
+ before the line immediately preceding a displayed equation.
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \[g H = H g \quad \text{for all} \enspace g \in G.\]
+ \end{vtiebotdisp}
+
+ Follow-up paragraph after and outside of the \code{vtiebotdisp}-environment.
+\end{typoginspect}
+
+\paragraph{\code{vtiebotdisptoppar}}\leavevmode\par
+
+\begin{typoginspect}{vtiebotdisptoppar}
+ \displaywidowpenalty=150
+ \begin{vtiebotdisptoppar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\displaywidowpenalty}
+ before the line immediately preceding a displayed equation.
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \begin{breakabledisplay}
+ \begin{displaymath}
+ g H = H g \quad \text{for all} \enspace g \in G.
+ \end{displaymath}
+ \end{breakabledisplay}
+
+ In this example we need a paragraph that follows the displayed math.
+ So, we have to type some more text here
+ to be able to demonstrate the action of the environment.
+ \end{vtiebotdisptoppar}
+\end{typoginspect}
+
+\clearpage
+\section{Breakable Displayed Equations}
+
+\newcommand*{\binaryminus}{\mathbin{-}}
+\newcommand*{\diracadj}[1]{\overline{#1}}
+\newcommand*{\unaryminus}{{-}}
+
+\begin{typoginspect}{breakabledisplay}
+ \begin{breakabledisplay}
+ \begin{align*}
+ \diracadj{\psi}(x) \mathop{\partial_\mu} \psi(x)
+ \mapsto \diracadj{\psi'}(x) \mathop{\partial_\mu} \psi'(x)
+ &= e^{i \alpha(x)} \diracadj{\psi}(x) \mathop{\partial_\mu} \bigl( e^{\unaryminus i \alpha(x)} \psi(x) \bigr) \\
+ &= \underbrace{\diracadj{\psi}(x) \mathop{\partial_\mu} \psi(x)}_{\text{free particle}}
+ \mskip\medmuskip \binaryminus \mskip\medmuskip i \, \diracadj{\psi}(x)
+ \underbrace{\mathop{\partial_\mu} \bigl( \alpha(x) \bigr)}_{\mathclap{\text{vector field}}} \psi(x).
+ \end{align*}
+ \end{breakabledisplay}
+\end{typoginspect}
+
+\clearpage
+\section{\packagename{Setspace} Front-End}
+
+\fontsizeinfo{defaultsize}
+Current settings are \defaultsize{}
+and \code{\string\typogfontsize} is \the\typogfontsize.
+
+\newcommand*{\absbls}{12pt plus 1pt minus .5pt}
+\paragraph{\code{\string\setbaselineskip\{\absbls\}}}
+\resetbaselineskip
+\setbaselineskip{10pt + 2.75pt}% addition
+\setbaselineskip{10.5pt * 100 / 105}% scaling
+\setbaselineskip{11.8pt * 85 / 100}% scaling
+\setbaselineskip{\absbls}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+\newcommand*{\relbls}{130}
+\paragraph{\code{\string\setbaselineskippercentage\{\relbls\}}}
+\setbaselineskippercentage{1 + 2 + .3333 * 100 + 100 * 0.6667}% float expression
+\setbaselineskippercentage{\relbls}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+\newcommand*{\absled}{1.5pt}
+\paragraph{\code{\string\setleading\{\absled\}}}
+\setleading{1pt / -2.0}% negative leading
+\setleading{\absled}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+\newcommand*{\relled}{30}
+\paragraph{\code{\string\setleadingpercentage\{\relled\}}}
+\setleadingpercentage{10 - 25 / 2}% negative leading
+\setleadingpercentage{\relled}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+\medskip
+
+\setstretch{1}
+\texbookbaselineskipsamplecredits
+
+\clearpage
+\section{Smooth Ragged}
+
+\begin{exemplary}
+ \newcommand*{\ragwidth}{10pt}
+ \centering
+ \caption[Comparison of ragged right typesetting]
+ {Comparison of ragged right typesetting.
+ The first example uses \code{RaggedRight} of \packagename{ragged2e}
+ the second \code{smoothraggedrightpar} of \packagename{typog}.
+ Both examples share a \code{\string\fussy}~setting and
+ a \ragwidth~wide ragged right margin.\label{ex:smoothraggedright}}
+
+ \setlength{\RaggedRightRightskip}{0pt plus \ragwidth}
+
+ %\def\smoothraggedrightgenerator{quintuplet}
+ %\def\smoothraggedrightgenerator{septuplet}
+ \setlength{\smoothraggedrightragwidth}{\ragwidth}
+ %\def\smoothraggedrightfuzzfactor{.667}
+
+ \iffalse
+ \begin{quote}
+ \begin{RaggedRight}\examplesetup
+ \texbookparshapeskipsample
+ \end{RaggedRight}
+ \end{quote}
+
+ \begin{quote}
+ \begin{smoothraggedrightpar}\examplesetup
+ \texbookparshapeskipsample
+ \end{smoothraggedrightpar}
+ \end{quote}
+ \else
+ \exampleparbox[RaggedRight-reference]{\RaggedRight\texbooktolerancesample}
+ \qquad
+ \exampleparbox[smoothraggedrightpar]{\smoothraggedrightpar\texbooktolerancesample}
+ \fi
+
+ \texbookparshapeskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+ %--\setlength{\smoothraggedrightparindent}{25pt}
+ %--\setlength{\parindent}{0pt}
+
+\noindent
+\code{\string\parindent}=\the\parindent,
+visually: \rule{.1pt}{.8em}\kern\parindent\rule{.1pt}{.8em};
+
+\noindent
+\code{\string\smoothraggedrightleftskip}=\the\smoothraggedrightleftskip.
+\code{\string\smoothraggedrightparindent}=\the\smoothraggedrightparindent.
+\smallskip
+
+{
+ %--\setlength{\smoothraggedrightragwidth}{8pt}
+ \begin{smoothraggedright}
+ \texbooktolerancesample
+
+ \texbooktolerancesample
+ \end{smoothraggedright}
+}
+
+\medskip
+
+{
+ \setlength{\smoothraggedrightragwidth}{15pt}
+
+ \newcommand*{\definitionnilpotent}{%
+ Eine Abbildung oder ein Operator~\(A\)
+ heißen nilpotent vom Grad~\(k\), falls \(k \in N\)
+ die kleinste Zahl ist, für die gilt: \(A^k = 0\).}
+
+ \begin{otherlanguage}{german}
+ \parbox[t]{60pt}{\fussy\RaggedRight\definitionnilpotent}
+ \hspace{40pt}
+ \parbox[t]{60pt}{\fussy\smoothraggedright\definitionnilpotent}
+ \end{otherlanguage}
+}
+
+\clearpage
+\begin{RaggedRight}
+ \begin{thebibliography}{0}
+ \bibitem{knuth:1986}
+ \bibauthor{Knuth, D.~E.},
+ \bibtitle{The \TeX{}book},
+ Vol.~A of Computers\&Typesetting,
+ Addison Wesley, Reading\kernedslash*MA,
+ 1986.
+ \end{thebibliography}
+\end{RaggedRight}
+\end{document}
+\endinput
+%%
+%% End of file `typog-example.tex'.
diff --git a/Master/texmf-dist/doc/latex/typog/typog-grep.1.pdf b/Master/texmf-dist/doc/latex/typog/typog-grep.1.pdf
new file mode 100644
index 00000000000..09647860d5d
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog-grep.1.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/latex/typog/typog-grep.pod b/Master/texmf-dist/doc/latex/typog/typog-grep.pod
new file mode 100644
index 00000000000..83f4f11f474
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog-grep.pod
@@ -0,0 +1,345 @@
+=begin man
+
+.\" Turn off justification.
+.na
+
+=end man
+
+=head1 NAME
+
+typog-grep - grep for typog-inspect elements in LaTeX log files
+
+=head1 SYNOPSIS
+
+=over
+
+=item B<typog-grep> -a|--all|--any [I<OPTION>...] F<LOG-FILE>...
+
+=item B<typog-grep> [I<OPTION>...] I<REGEXP> F<LOG-FILE>...
+
+=back
+
+The first form shows all C<E<lt>typog-inspect id="I<ID>" ...E<gt>> elements in F<LOG-FILE>.
+
+The second form shows the contents of C<E<lt>typog-inspect id="I<ID>" ...E<gt>> elements
+whose I<ID>s match I<REGEXP> in F<LOG-FILE>.
+
+If no F<LOG-FILE> is given read from F<stdin>.
+The S<filename C<->> is synonymous to F<stdin>.
+
+=head1 DESCRIPTION
+
+B<typog-grep> is a tailored post-processor for LaTeX log files
+and the C<typoginspect> environment as provided by S<package typog>.
+It shares more with the venerable
+L<B<sgrep>|https://www.cs.helsinki.fi/u/jjaakkol/sgrep.html>
+than with S<POSIX L<B<grep>|https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html>>.
+
+The LaTeX user brackets her text in
+
+ \begin{typoginspect}{ID}
+ Text and code to investigate
+ \end{typoginspect}
+
+where I<ID> is used to identify one or more bracketed snippets.
+I<ID> does not have to be unique.
+The I<REGEXP> mechanism makes it easy to select groups of related I<ID>s
+if they are named accordingly.
+
+In F<LOG-FILE> the environment shows up, packed with tracing information, as
+
+=begin texinfo
+
+@display
+@relax
+
+=end texinfo
+
+ <typog-inspect id="ID" job="JOB-NAME" line="LINE-NUMBER" page="PAGE-NUMBER">
+ Trace Data
+ </typog-inspect>
+
+=begin texinfo
+
+@end display
+@relax
+
+=end texinfo
+
+where all the capital-letter sequences are meta-variables
+and in particular
+I<JOB-NAME> is the expansion of C<\jobname>,
+I<LINE-NUMBER> is the LaTeX source file line number
+of the beginning of the C<typoginspect> environment,
+and I<PAGE-NUMBER> is the page where
+the output of S<C<Text and code to investigate>> occurs.
+
+B<typog-grep> reveals the contents of F<LOG-FILE>
+between C<E<lt>typog-inspect id="I<ID>" ...E<gt>>
+and C<E<lt>/typog-inspectE<gt>> excluding the XML-tags.
+Access the I<JOB-NAME>, I<LINE-NUMBER>, and I<PAGE-NUMBER>
+with the commandline options
+B<--job-name>, B<--line-number>, and B<--page-number>, respectively.
+Use B<--id> to show the name of the IDs that matched I<REGEXP>.
+
+C<typoginspect> environments can be nested.
+B<typog-grep> respects the nesting,
+i.e., if the I<ID> of the nested environment does not match I<REGEXP>
+it will not be included in the program's output.
+
+=head1 OPTIONS
+
+The list of options is sorted by the names of the long options.
+
+=over 4
+
+=item B<-a>, B<--all>, B<--any>
+
+ID-discovery mode:
+Show all C<typog-inspect> elements independent of any matching patterns.
+
+=item B<--color>, B<colour> I<WHEN>
+
+Colorize specific log contents for the matching ids.
+The S<argument I<WHEN>> determines when to apply color:
+C<always>, C<never>, S<or C<auto>>.
+The setting C<auto> checks whether standard output has been redirected.
+This is the default.
+
+=item B<-C>, B<--config> I<KEY>=I<VALUE>[:I<KEY>=I<VALUE>[:...]]
+
+Set one or more configuration I<KEY> to I<VALUE> pairs.
+See S<Sec. CONFIGURATION> below for a description of all available configuration items.
+Use option B<--show-config> to display the default configuration.
+
+=item B<--debug>
+
+Turn on debug output on F<stderr>.
+
+=item B<-h>, B<--help>
+
+Display brief help then exit.
+
+=item B<-i>, B<--[no-]id>
+
+Print the actual id name that matched I<REGEXP>.
+Control the appearance of the matching id with configuration S<item C<id-heading>>.
+
+=item B<-y>, B<--[no-]ignore-case>
+
+Match ids while ignoring case distinctions in patterns and data.
+
+=item B<-j>, B<--[no-]job-name>
+
+Print the C<\jobname> that B<tex> associated with the input file.
+
+=item B<-n>, B<--[no-]line-number>
+
+Print the line number where the S<C<typoginspect> environment>
+was encountered in the LaTeX source file.
+
+=item B<-N>, B<--[no-]log-line-number>
+
+Print the line number of the F<log>-file where the current line was encountered.
+
+=item B<-p>, B<--[no-]page-number>
+
+Print page number where the contents of the S<C<typoginspect> environment>
+starts in the typeset document.
+
+=item B<-P>, B<--[no-]pager>
+
+Redirect output from F<stdout> to the configured pager.
+
+=item B<--show-config>
+
+Show the default configuration and exit.
+
+=item B<-V>, B<--version>
+
+Show version information and exit.
+
+=item B<-w>, B<--[no-]word-regexp>
+
+Match only whole words.
+
+=back
+
+=head1 CONFIGURATION
+
+=over 4
+
+=item C<id-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing matching ids in inline-mode,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%s:>.>
+
+=item C<id-heading>=C<0>E<verbar>C<1>
+
+Choose between printing the matching ids with S<option B<--id>>:
+S<Inline (C<0>)> or heading before the matching data (C<1>).
+S<Default: C<0>.>
+
+=item C<id-heading-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing matching ids in heading-mode,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<--E<gt> %s E<lt>-->.>
+
+=item C<id-indent>=I<INDENT>
+
+Indentation of nested typog-inspect tags.
+Only used in ``discovery'' mode (first form), i.e., if B<--all> is active.
+S<Default: 8.>
+
+=item C<id-max-length>=I<MAXIMUM-LENGTH>
+
+Set the maximum length of a matching id for printing.
+It a matching id exceeds this length it will be truncated
+and the last three characters (short of I<MAXIMUM-LENGTH>) will be replaced by dots.
+S<Default: 40.>
+
+=item C<line-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing TeX source line numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%5d>.>
+
+=item C<log-line-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing log line numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%6d>.>
+
+=item C<page-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing page numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<[%3d]>.>
+
+=item C<pager>=I<PAGER>
+
+Name of pager application to pipe output into
+if run with S<option B<--pager>>.
+S<Default: C<less>>.
+
+=item C<pager-flags>=I<FLAGS>
+
+Pass I<FLAGS> to I<PAGER>.
+S<Default: C<--quit-if-one-screen>>.
+
+=item Color Configuration
+
+For the syntax of the color specifications consult
+the manual page of Term::ANSIColor(pm).
+
+=over 4
+
+=item C<file-header-color>
+
+Color of the filename header.
+
+=item C<fill-state-color>
+
+Color of the messages that report ``Underfull hbox'' or ``Overfull hbox''.
+
+=item C<first-vbox-color>
+
+Color of the first vbox on a page.
+
+=item C<font-spec-color>
+
+Color of font specifications.
+
+=item C<horizontal-break-candidate-color>
+
+Color of lines with horizontal-breakpoint S<candidates C<@>>.
+
+=item C<horizontal-breakpoint-color>
+
+Color of lines with horizontal S<breakpoints C<@@>>.
+
+=item C<id-color>
+
+Color of matching ids when printed inline.
+
+=item C<id-heading-color>
+
+Color of matching ids when printed in heading form.
+
+=item C<line-break-pass-color>
+
+Color of the lines showing which pass (e.g., C<@firstpass>)
+of the line-breaking algorithm is active.
+
+=item C<line-number-color>
+
+Color of TeX-source-file line numbers.
+
+=item C<log-line-number-color>
+
+Color of log-file line numbers.
+
+=item C<math-color>
+
+Color used for math expressions including their font specs.
+
+=item C<page-number-color>
+
+Color of page numbers of the final output.
+
+=item C<tightness-color>
+
+Color of lines with Tight/Loose hbox reports.
+
+=item C<vertical-breakpoint-color>
+
+Color of possible vertical breakpoints.
+
+=back
+
+=back
+
+=head2 Brief summary of colors and attributes
+
+=over 4
+
+=item Foreground Color
+
+C<black>, C<red>, C<green>, C<yellow>,
+C<blue>, C<magenta>, C<cyan>, C<white>,
+
+Prefix with C<bright_> for high-intensity or bold foreground.
+
+=item Foreground Grey
+
+C<grey0>, ..., C<grey23>
+
+=item Background Color
+
+C<on_black>, C<on_red>, C<on_green>, C<on_yellow>,
+S<C<on_blue>>, S<C<on_magenta>>, S<C<on_cyan>>, S<C<on_white>>
+
+Replace C<on_> with C<on_bright_> for high-intensity or bold background.
+
+=item Background Grey
+
+C<on_grey0>, ..., C<on_grey23>
+
+=item Text Attribute
+
+C<bold>, C<dark>, C<italic>, C<underline>, C<reverse>
+
+=back
+
+=head1 EXIT STATUS
+
+The exit status is 0 if at least one I<ID> matched I<REGEXP>,
+1 if no I<ID> matched I<REGEXP>, and 2 if an error occurred.
+
+=head1 SEE ALSO
+
+B<grep>(1), B<printf>(3), B<Term::ANSIColor>(pm)
+
+=cut
diff --git a/Master/texmf-dist/doc/latex/typog/typog-nomt.tex b/Master/texmf-dist/doc/latex/typog/typog-nomt.tex
new file mode 100644
index 00000000000..ebac4efd1f7
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog-nomt.tex
@@ -0,0 +1,73 @@
+%%
+%% This is file `typog-nomt.tex',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `nomicrotype')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+\documentclass[]{article}
+
+\usepackage[english]{babel}
+
+\usepackage{csquotes}
+\DeclareQuoteStyle{typog-guillemets}
+ {\doubleguillemetright}
+ {\doubleguillemetleft}
+ {\singleguillemetright}
+ {\singleguillemetleft}
+
+\usepackage[]{typog}
+
+\newcommand*{\packagename}[1]{\mbox{\textsf{#1}}}
+
+\begin{document}
+\begin{center}
+ \Huge\bf\sf
+ TypoG Examples \\
+ without Package~\packagename{microtype}
+\end{center}
+
+\bigskip
+
+\noindent
+This example \LaTeX-document uses package~\packagename{typog}
+\emph{without} package~\packagename{microtype}.
+
+We want \packagename{typog} to be as usable as possible even without
+the nice features that \packagename{microtype} offers.
+After all \packagename{typog} is just a front-end for it.
+
+As we are testing a special configuration here anyhow,
+we hook up our quotes with package~csquotes
+to check whether they interact ok.
+{\setquotestyle{typog-guillemets}%
+ \enquote{This is the outer part of the phrase
+ which contains the \enquote{inner part}.}}
+\end{document}
+\endinput
+%%
+%% End of file `typog-nomt.tex'.
diff --git a/Master/texmf-dist/doc/latex/typog/typog.ist b/Master/texmf-dist/doc/latex/typog/typog.ist
new file mode 100644
index 00000000000..9b8104b16c0
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog.ist
@@ -0,0 +1,41 @@
+%%
+%% This is file `typog.ist',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `index-style')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+actual '='
+delim_r "\\figuredash*"
+heading_prefix "\\pagebreak[3]\\smallskip\n\n{\\sffamily\\bfseries\\large "
+heading_suffix "}\\nopagebreak\n"
+headings_flag 1
+level '>'
+quote '!'
+\endinput
+%%
+%% End of file `typog.ist'.
diff --git a/Master/texmf-dist/doc/latex/typog/typog.pdf b/Master/texmf-dist/doc/latex/typog/typog.pdf
new file mode 100644
index 00000000000..9d00685045a
--- /dev/null
+++ b/Master/texmf-dist/doc/latex/typog/typog.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/man/man1/typog-grep.1 b/Master/texmf-dist/doc/man/man1/typog-grep.1
new file mode 100644
index 00000000000..372c87bc5ff
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/typog-grep.1
@@ -0,0 +1,428 @@
+.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+. if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{\
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "TYPOG-GREP 1"
+.TH TYPOG-GREP 1 "2024-05-07" "perl v5.36.0" "User Contributed Perl Documentation"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.\" Turn off justification.
+.na
+.SH "NAME"
+typog\-grep \- grep for typog\-inspect elements in LaTeX log files
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+.IP "\fBtypog-grep\fR \-a|\-\-all|\-\-any [\fI\s-1OPTION\s0\fR...] \fILOG-FILE\fR..." 4
+.IX Item "typog-grep -a|--all|--any [OPTION...] LOG-FILE..."
+.PD 0
+.IP "\fBtypog-grep\fR [\fI\s-1OPTION\s0\fR...] \fI\s-1REGEXP\s0\fR \fILOG-FILE\fR..." 4
+.IX Item "typog-grep [OPTION...] REGEXP LOG-FILE..."
+.PD
+.PP
+The first form shows all \f(CW\*(C`<typog\-inspect id="\f(CIID\f(CW" ...>\*(C'\fR elements in \fILOG-FILE\fR.
+.PP
+The second form shows the contents of \f(CW\*(C`<typog\-inspect id="\f(CIID\f(CW" ...>\*(C'\fR elements
+whose \fI\s-1ID\s0\fRs match \fI\s-1REGEXP\s0\fR in \fILOG-FILE\fR.
+.PP
+If no \fILOG-FILE\fR is given read from \fIstdin\fR.
+The filename\ \f(CW\*(C`\-\*(C'\fR is synonymous to \fIstdin\fR.
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBtypog-grep\fR is a tailored post-processor for LaTeX log files
+and the \f(CW\*(C`typoginspect\*(C'\fR environment as provided by package\ typog.
+It shares more with the venerable
+\&\fBsgrep\fR <https://www.cs.helsinki.fi/u/jjaakkol/sgrep.html>
+than with \s-1POSIX\s0\ \fBgrep\fR <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html>.
+.PP
+The LaTeX user brackets her text in
+.PP
+.Vb 3
+\& \ebegin{typoginspect}{ID}
+\& Text and code to investigate
+\& \eend{typoginspect}
+.Ve
+.PP
+where \fI\s-1ID\s0\fR is used to identify one or more bracketed snippets.
+\&\fI\s-1ID\s0\fR does not have to be unique.
+The \fI\s-1REGEXP\s0\fR mechanism makes it easy to select groups of related \fI\s-1ID\s0\fRs
+if they are named accordingly.
+.PP
+In \fILOG-FILE\fR the environment shows up, packed with tracing information, as
+.PP
+.Vb 3
+\& <typog\-inspect id="ID" job="JOB\-NAME" line="LINE\-NUMBER" page="PAGE\-NUMBER">
+\& Trace Data
+\& </typog\-inspect>
+.Ve
+.PP
+where all the capital-letter sequences are meta-variables
+and in particular
+\&\fIJOB-NAME\fR is the expansion of \f(CW\*(C`\ejobname\*(C'\fR,
+\&\fILINE-NUMBER\fR is the LaTeX source file line number
+of the beginning of the \f(CW\*(C`typoginspect\*(C'\fR environment,
+and \fIPAGE-NUMBER\fR is the page where
+the output of \f(CW\*(C`Text\ and\ code\ to\ investigate\*(C'\fR occurs.
+.PP
+\&\fBtypog-grep\fR reveals the contents of \fILOG-FILE\fR
+between \f(CW\*(C`<typog\-inspect id="\f(CIID\f(CW" ...>\*(C'\fR
+and \f(CW\*(C`</typog\-inspect>\*(C'\fR excluding the XML-tags.
+Access the \fIJOB-NAME\fR, \fILINE-NUMBER\fR, and \fIPAGE-NUMBER\fR
+with the commandline options
+\&\fB\-\-job\-name\fR, \fB\-\-line\-number\fR, and \fB\-\-page\-number\fR, respectively.
+Use \fB\-\-id\fR to show the name of the IDs that matched \fI\s-1REGEXP\s0\fR.
+.PP
+\&\f(CW\*(C`typoginspect\*(C'\fR environments can be nested.
+\&\fBtypog-grep\fR respects the nesting,
+i.e., if the \fI\s-1ID\s0\fR of the nested environment does not match \fI\s-1REGEXP\s0\fR
+it will not be included in the program's output.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+The list of options is sorted by the names of the long options.
+.IP "\fB\-a\fR, \fB\-\-all\fR, \fB\-\-any\fR" 4
+.IX Item "-a, --all, --any"
+ID-discovery mode:
+Show all \f(CW\*(C`typog\-inspect\*(C'\fR elements independent of any matching patterns.
+.IP "\fB\-\-color\fR, \fBcolour\fR \fI\s-1WHEN\s0\fR" 4
+.IX Item "--color, colour WHEN"
+Colorize specific log contents for the matching ids.
+The argument\ \fI\s-1WHEN\s0\fR determines when to apply color:
+\&\f(CW\*(C`always\*(C'\fR, \f(CW\*(C`never\*(C'\fR, or\ \f(CW\*(C`auto\*(C'\fR.
+The setting \f(CW\*(C`auto\*(C'\fR checks whether standard output has been redirected.
+This is the default.
+.IP "\fB\-C\fR, \fB\-\-config\fR \fI\s-1KEY\s0\fR=\fI\s-1VALUE\s0\fR[:\fI\s-1KEY\s0\fR=\fI\s-1VALUE\s0\fR[:...]]" 4
+.IX Item "-C, --config KEY=VALUE[:KEY=VALUE[:...]]"
+Set one or more configuration \fI\s-1KEY\s0\fR to \fI\s-1VALUE\s0\fR pairs.
+See Sec.\ \s-1CONFIGURATION\s0 below for a description of all available configuration items.
+Use option \fB\-\-show\-config\fR to display the default configuration.
+.IP "\fB\-\-debug\fR" 4
+.IX Item "--debug"
+Turn on debug output on \fIstderr\fR.
+.IP "\fB\-h\fR, \fB\-\-help\fR" 4
+.IX Item "-h, --help"
+Display brief help then exit.
+.IP "\fB\-i\fR, \fB\-\-[no\-]id\fR" 4
+.IX Item "-i, --[no-]id"
+Print the actual id name that matched \fI\s-1REGEXP\s0\fR.
+Control the appearance of the matching id with configuration item\ \f(CW\*(C`id\-heading\*(C'\fR.
+.IP "\fB\-y\fR, \fB\-\-[no\-]ignore\-case\fR" 4
+.IX Item "-y, --[no-]ignore-case"
+Match ids while ignoring case distinctions in patterns and data.
+.IP "\fB\-j\fR, \fB\-\-[no\-]job\-name\fR" 4
+.IX Item "-j, --[no-]job-name"
+Print the \f(CW\*(C`\ejobname\*(C'\fR that \fBtex\fR associated with the input file.
+.IP "\fB\-n\fR, \fB\-\-[no\-]line\-number\fR" 4
+.IX Item "-n, --[no-]line-number"
+Print the line number where the \f(CW\*(C`typoginspect\*(C'\fR\ environment
+was encountered in the LaTeX source file.
+.IP "\fB\-N\fR, \fB\-\-[no\-]log\-line\-number\fR" 4
+.IX Item "-N, --[no-]log-line-number"
+Print the line number of the \fIlog\fR\-file where the current line was encountered.
+.IP "\fB\-p\fR, \fB\-\-[no\-]page\-number\fR" 4
+.IX Item "-p, --[no-]page-number"
+Print page number where the contents of the \f(CW\*(C`typoginspect\*(C'\fR\ environment
+starts in the typeset document.
+.IP "\fB\-P\fR, \fB\-\-[no\-]pager\fR" 4
+.IX Item "-P, --[no-]pager"
+Redirect output from \fIstdout\fR to the configured pager.
+.IP "\fB\-\-show\-config\fR" 4
+.IX Item "--show-config"
+Show the default configuration and exit.
+.IP "\fB\-V\fR, \fB\-\-version\fR" 4
+.IX Item "-V, --version"
+Show version information and exit.
+.IP "\fB\-w\fR, \fB\-\-[no\-]word\-regexp\fR" 4
+.IX Item "-w, --[no-]word-regexp"
+Match only whole words.
+.SH "CONFIGURATION"
+.IX Header "CONFIGURATION"
+.ie n .IP """id\-format""=\fI\s-1FORMAT\s0\fR" 4
+.el .IP "\f(CWid\-format\fR=\fI\s-1FORMAT\s0\fR" 4
+.IX Item "id-format=FORMAT"
+Control the \fI\s-1FORMAT\s0\fR for printing matching ids in inline-mode,
+where \fI\s-1FORMAT\s0\fR is passed to Perl's \f(CW\*(C`printf\*(C'\fR.
+Default:\ \f(CW%s:\fR.
+.ie n .IP """id\-heading""=0|1" 4
+.el .IP "\f(CWid\-heading\fR=\f(CW0\fR|\f(CW1\fR" 4
+.IX Item "id-heading=0|1"
+Choose between printing the matching ids with option\ \fB\-\-id\fR:
+Inline\ (\f(CW0\fR) or heading before the matching data (\f(CW1\fR).
+Default:\ \f(CW0\fR.
+.ie n .IP """id\-heading\-format""=\fI\s-1FORMAT\s0\fR" 4
+.el .IP "\f(CWid\-heading\-format\fR=\fI\s-1FORMAT\s0\fR" 4
+.IX Item "id-heading-format=FORMAT"
+Control the \fI\s-1FORMAT\s0\fR for printing matching ids in heading-mode,
+where \fI\s-1FORMAT\s0\fR is passed to Perl's \f(CW\*(C`printf\*(C'\fR.
+Default:\ \f(CW\*(C`\-\->\ %s\ <\-\-\*(C'\fR.
+.ie n .IP """id\-indent""=\fI\s-1INDENT\s0\fR" 4
+.el .IP "\f(CWid\-indent\fR=\fI\s-1INDENT\s0\fR" 4
+.IX Item "id-indent=INDENT"
+Indentation of nested typog-inspect tags.
+Only used in ``discovery'' mode (first form), i.e., if \fB\-\-all\fR is active.
+Default:\ 8.
+.ie n .IP """id\-max\-length""=\fIMAXIMUM-LENGTH\fR" 4
+.el .IP "\f(CWid\-max\-length\fR=\fIMAXIMUM-LENGTH\fR" 4
+.IX Item "id-max-length=MAXIMUM-LENGTH"
+Set the maximum length of a matching id for printing.
+It a matching id exceeds this length it will be truncated
+and the last three characters (short of \fIMAXIMUM-LENGTH\fR) will be replaced by dots.
+Default:\ 40.
+.ie n .IP """line\-number\-format""=\fI\s-1FORMAT\s0\fR" 4
+.el .IP "\f(CWline\-number\-format\fR=\fI\s-1FORMAT\s0\fR" 4
+.IX Item "line-number-format=FORMAT"
+Control the \fI\s-1FORMAT\s0\fR for printing TeX source line numbers,
+where \fI\s-1FORMAT\s0\fR is passed to Perl's \f(CW\*(C`printf\*(C'\fR.
+Default:\ \f(CW%5d\fR.
+.ie n .IP """log\-line\-number\-format""=\fI\s-1FORMAT\s0\fR" 4
+.el .IP "\f(CWlog\-line\-number\-format\fR=\fI\s-1FORMAT\s0\fR" 4
+.IX Item "log-line-number-format=FORMAT"
+Control the \fI\s-1FORMAT\s0\fR for printing log line numbers,
+where \fI\s-1FORMAT\s0\fR is passed to Perl's \f(CW\*(C`printf\*(C'\fR.
+Default:\ \f(CW%6d\fR.
+.ie n .IP """page\-number\-format""=\fI\s-1FORMAT\s0\fR" 4
+.el .IP "\f(CWpage\-number\-format\fR=\fI\s-1FORMAT\s0\fR" 4
+.IX Item "page-number-format=FORMAT"
+Control the \fI\s-1FORMAT\s0\fR for printing page numbers,
+where \fI\s-1FORMAT\s0\fR is passed to Perl's \f(CW\*(C`printf\*(C'\fR.
+Default:\ \f(CW\*(C`[%3d]\*(C'\fR.
+.ie n .IP """pager""=\fI\s-1PAGER\s0\fR" 4
+.el .IP "\f(CWpager\fR=\fI\s-1PAGER\s0\fR" 4
+.IX Item "pager=PAGER"
+Name of pager application to pipe output into
+if run with option\ \fB\-\-pager\fR.
+Default:\ \f(CW\*(C`less\*(C'\fR.
+.ie n .IP """pager\-flags""=\fI\s-1FLAGS\s0\fR" 4
+.el .IP "\f(CWpager\-flags\fR=\fI\s-1FLAGS\s0\fR" 4
+.IX Item "pager-flags=FLAGS"
+Pass \fI\s-1FLAGS\s0\fR to \fI\s-1PAGER\s0\fR.
+Default:\ \f(CW\*(C`\-\-quit\-if\-one\-screen\*(C'\fR.
+.IP "Color Configuration" 4
+.IX Item "Color Configuration"
+For the syntax of the color specifications consult
+the manual page of Term::ANSIColor(pm).
+.RS 4
+.ie n .IP """file\-header\-color""" 4
+.el .IP "\f(CWfile\-header\-color\fR" 4
+.IX Item "file-header-color"
+Color of the filename header.
+.ie n .IP """fill\-state\-color""" 4
+.el .IP "\f(CWfill\-state\-color\fR" 4
+.IX Item "fill-state-color"
+Color of the messages that report ``Underfull hbox'' or ``Overfull hbox''.
+.ie n .IP """first\-vbox\-color""" 4
+.el .IP "\f(CWfirst\-vbox\-color\fR" 4
+.IX Item "first-vbox-color"
+Color of the first vbox on a page.
+.ie n .IP """font\-spec\-color""" 4
+.el .IP "\f(CWfont\-spec\-color\fR" 4
+.IX Item "font-spec-color"
+Color of font specifications.
+.ie n .IP """horizontal\-break\-candidate\-color""" 4
+.el .IP "\f(CWhorizontal\-break\-candidate\-color\fR" 4
+.IX Item "horizontal-break-candidate-color"
+Color of lines with horizontal-breakpoint candidates\ \f(CW\*(C`@\*(C'\fR.
+.ie n .IP """horizontal\-breakpoint\-color""" 4
+.el .IP "\f(CWhorizontal\-breakpoint\-color\fR" 4
+.IX Item "horizontal-breakpoint-color"
+Color of lines with horizontal breakpoints\ \f(CW\*(C`@@\*(C'\fR.
+.ie n .IP """id\-color""" 4
+.el .IP "\f(CWid\-color\fR" 4
+.IX Item "id-color"
+Color of matching ids when printed inline.
+.ie n .IP """id\-heading\-color""" 4
+.el .IP "\f(CWid\-heading\-color\fR" 4
+.IX Item "id-heading-color"
+Color of matching ids when printed in heading form.
+.ie n .IP """line\-break\-pass\-color""" 4
+.el .IP "\f(CWline\-break\-pass\-color\fR" 4
+.IX Item "line-break-pass-color"
+Color of the lines showing which pass (e.g., \f(CW@firstpass\fR)
+of the line-breaking algorithm is active.
+.ie n .IP """line\-number\-color""" 4
+.el .IP "\f(CWline\-number\-color\fR" 4
+.IX Item "line-number-color"
+Color of TeX-source-file line numbers.
+.ie n .IP """log\-line\-number\-color""" 4
+.el .IP "\f(CWlog\-line\-number\-color\fR" 4
+.IX Item "log-line-number-color"
+Color of log-file line numbers.
+.ie n .IP """math\-color""" 4
+.el .IP "\f(CWmath\-color\fR" 4
+.IX Item "math-color"
+Color used for math expressions including their font specs.
+.ie n .IP """page\-number\-color""" 4
+.el .IP "\f(CWpage\-number\-color\fR" 4
+.IX Item "page-number-color"
+Color of page numbers of the final output.
+.ie n .IP """tightness\-color""" 4
+.el .IP "\f(CWtightness\-color\fR" 4
+.IX Item "tightness-color"
+Color of lines with Tight/Loose hbox reports.
+.ie n .IP """vertical\-breakpoint\-color""" 4
+.el .IP "\f(CWvertical\-breakpoint\-color\fR" 4
+.IX Item "vertical-breakpoint-color"
+Color of possible vertical breakpoints.
+.RE
+.RS 4
+.RE
+.SS "Brief summary of colors and attributes"
+.IX Subsection "Brief summary of colors and attributes"
+.IP "Foreground Color" 4
+.IX Item "Foreground Color"
+\&\f(CW\*(C`black\*(C'\fR, \f(CW\*(C`red\*(C'\fR, \f(CW\*(C`green\*(C'\fR, \f(CW\*(C`yellow\*(C'\fR,
+\&\f(CW\*(C`blue\*(C'\fR, \f(CW\*(C`magenta\*(C'\fR, \f(CW\*(C`cyan\*(C'\fR, \f(CW\*(C`white\*(C'\fR,
+.Sp
+Prefix with \f(CW\*(C`bright_\*(C'\fR for high-intensity or bold foreground.
+.IP "Foreground Grey" 4
+.IX Item "Foreground Grey"
+\&\f(CW\*(C`grey0\*(C'\fR, ..., \f(CW\*(C`grey23\*(C'\fR
+.IP "Background Color" 4
+.IX Item "Background Color"
+\&\f(CW\*(C`on_black\*(C'\fR, \f(CW\*(C`on_red\*(C'\fR, \f(CW\*(C`on_green\*(C'\fR, \f(CW\*(C`on_yellow\*(C'\fR,
+\&\f(CW\*(C`on_blue\*(C'\fR, \f(CW\*(C`on_magenta\*(C'\fR, \f(CW\*(C`on_cyan\*(C'\fR, \f(CW\*(C`on_white\*(C'\fR
+.Sp
+Replace \f(CW\*(C`on_\*(C'\fR with \f(CW\*(C`on_bright_\*(C'\fR for high-intensity or bold background.
+.IP "Background Grey" 4
+.IX Item "Background Grey"
+\&\f(CW\*(C`on_grey0\*(C'\fR, ..., \f(CW\*(C`on_grey23\*(C'\fR
+.IP "Text Attribute" 4
+.IX Item "Text Attribute"
+\&\f(CW\*(C`bold\*(C'\fR, \f(CW\*(C`dark\*(C'\fR, \f(CW\*(C`italic\*(C'\fR, \f(CW\*(C`underline\*(C'\fR, \f(CW\*(C`reverse\*(C'\fR
+.SH "EXIT STATUS"
+.IX Header "EXIT STATUS"
+The exit status is 0 if at least one \fI\s-1ID\s0\fR matched \fI\s-1REGEXP\s0\fR,
+1 if no \fI\s-1ID\s0\fR matched \fI\s-1REGEXP\s0\fR, and 2 if an error occurred.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fBgrep\fR(1), \fBprintf\fR(3), \fBTerm::ANSIColor\fR(pm)
diff --git a/Master/texmf-dist/doc/man/man1/typog-grep.man1.pdf b/Master/texmf-dist/doc/man/man1/typog-grep.man1.pdf
new file mode 100644
index 00000000000..ca0157d129b
--- /dev/null
+++ b/Master/texmf-dist/doc/man/man1/typog-grep.man1.pdf
Binary files differ
diff --git a/Master/texmf-dist/scripts/typog/typog-grep.pl b/Master/texmf-dist/scripts/typog/typog-grep.pl
new file mode 100755
index 00000000000..bc7f0e98fbd
--- /dev/null
+++ b/Master/texmf-dist/scripts/typog/typog-grep.pl
@@ -0,0 +1,614 @@
+#! /usr/bin/env perl
+
+use autodie qw(:all);
+use strict;
+use warnings;
+
+use Data::Dumper ();
+use English;
+use File::Basename ();
+use Getopt::Long;
+use IO::File;
+use IO::Handle;
+use Term::ANSIColor ();
+
+use constant COMMAND_NAME => File::Basename::basename($PROGRAM_NAME);
+
+my $DEBUG = 0;
+my $MATCH_COUNT = 0;
+my $OUTPUT_IS_REDIRECTED;
+
+sub fail_with_error {
+ print STDERR join('', COMMAND_NAME, ': ', @_, "\n");
+ exit 2;
+}
+
+sub issue_warning {
+ print STDERR join('', COMMAND_NAME, ': warning: ', @_, "\n");
+}
+
+sub debug_print {
+ return unless $DEBUG;
+ print STDERR "+ @_\n";
+}
+
+sub quote_filesystem {qq("$_[0]")}
+sub quote_literal {qq(`$_[0]')}
+
+sub limit_string_length {
+ my ($a_string, $a_maximum_length) = @_;
+
+ if (length $a_string <= $a_maximum_length) {
+ $a_string;
+ } else {
+ substr($a_string, 0, $a_maximum_length - 3) . '...';
+ }
+}
+
+## We set all colors to `undef' and fill them later with the values
+## of the actual configuration.
+my $highlight_patterns = {
+ PARTIAL_LINE => {
+ FONT_SPEC => [qr#
+ \\
+ (?: OMS | OMX | OT1 | T1 | TS1 | U )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ #x, undef],
+ MATH => [qr#
+ \$
+ \\
+ (?: LMS | OML )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ .*?
+ \$
+ #x, undef]
+ },
+ WHOLE_LINE => {
+ FILL_STATE => [qr#^(?:Under|Over)full \\hbox .*$#, undef],
+ FIRST_VBOX => [qr#^%%#, undef],
+ HORIZONTAL_BREAKPOINT => [qr#^@@\d+:.*$#, undef],
+ HORIZONTAL_BREAK_CANDIDATE => [qr#^@[\\ ].*$#, undef],
+ LINE_BREAK_PASS => [qr#^@[a-z]+?pass#, undef],
+ TIGHTNESS => [qr#^(?:Loose|Tight) \\hbox .*$#, undef],
+ VERTICAL_BREAKPOINT => [qr#^% t=\d+.*$#, undef]
+ }
+};
+
+sub colorize_line {
+ my ($configuration, $line) = @_;
+
+ foreach my $pattern_color_pair (values %{$highlight_patterns->{WHOLE_LINE}}) {
+ next unless $pattern_color_pair->[1];
+ return Term::ANSIColor::colored($line, $pattern_color_pair->[1])
+ if $line =~ $pattern_color_pair->[0];
+ }
+ return $line if $line =~ m#^\.#; # we do not paint box contents yet
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{MATH}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{MATH}->[1])
+ #egx;
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[1])
+ #egx;
+
+ return $line;
+}
+
+my $open_or_close_tag_regexp = qr#^</?typog-inspect[ >]#; # somewhat sloppy definition
+my $close_tag_regexp = qr#^</typog-inspect>#;
+my $open_tag_regexp =
+ qr#^
+ <typog-inspect \s+
+ id="(?<id_match> .*?)" \s+
+ job="(?<job_match> .*?)" \s+
+ line="(?<line_match> .*?)" \s+
+ page="(?<page_match> .*?)"
+ >#x;
+
+sub grep_log_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $job_name;
+ my $line_number = 0; # line number in the log file we are inspecting, i.e., $filename
+ my $match_count = 0;
+ my $source_line_number; # line number in TeX file the log refers to, i.e., "$job_name.tex"
+ my $page_number;
+ my $regexp_modifier = $options->{IGNORE_CASE} ? 'i' : '';
+ my $id_value;
+ my @nesting_levels;
+
+ if ($options->{WORD_REGEXP}) {
+ $id_regexp = "\\b$id_regexp\\b";
+ }
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if (@nesting_levels and $nesting_levels[-1] and $line !~ $open_or_close_tag_regexp) {
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ if ($options->{ID} and not $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_INLINE_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id = Term::ANSIColor::colored($formatted_id ,
+ $configuration->{COLORS}->{ID_COLOR});
+ }
+ print $formatted_id, ' ';
+ }
+
+ if ($options->{COLORIZE_OUTPUT}) {
+ print colorize_line($configuration, $line);
+ } else {
+ print $line;
+ }
+ print "\n";
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ $job_name = $+{job_match};
+ $source_line_number = $+{line_match};
+ $page_number = $+{page_match};
+
+ my $found_matching_id = ($id_value =~ m/(?$regexp_modifier)$id_regexp/) ? 1 : 0;
+ push @nesting_levels, $found_matching_id;
+ if ($found_matching_id) {
+ ++$MATCH_COUNT; # global count -- needed for return code of program
+ ++$match_count; # per file count -- needed to be able to separate the hunks
+
+ print "\n" if $match_count >= 2;
+ if ($options->{ID} and $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_HEADING_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id =
+ Term::ANSIColor::colored($formatted_id,
+ $configuration->{COLORS}->{ID_HEADING_COLOR});
+ }
+ print $formatted_id, "\n";
+ }
+ }
+ }
+ }
+}
+
+sub show_ids_in_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $line_number = 0;
+ my @nesting_levels;
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ my $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ my $job_name = $+{job_match};
+ my $source_line_number = $+{line_match};
+ my $page_number = $+{page_match};
+
+ ++$MATCH_COUNT;
+ push @nesting_levels, 1;
+
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ my $indent = $configuration->{ID_INDENT} * (@nesting_levels - 1);
+ print ' ' x $indent, $id_value, "\n";
+ }
+ }
+}
+
+sub open_file_for_reading {
+ my $filename = shift;
+
+ my $file;
+
+ if ($filename eq 'stdin') {
+ $file = IO::Handle->new();
+ $file->fdopen(fileno(STDIN), 'r') or
+ fail_with_error("cannot open stdin: $OS_ERROR");
+ } else {
+ $file = IO::File->new($filename, 'r') or
+ fail_with_error("cannot open @{[quote_filesystem($filename)]}: $OS_ERROR");
+ }
+
+ $file;
+}
+
+sub close_file {
+ my ($file, $filename) = shift;
+
+ $file->close or
+ issue_warning("problems while closing @{[quote_filesystem($filename)]}: $OS_ERROR");
+}
+
+sub grep_or_show {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ if ($options->{SHOW_ALL_IDS}) {
+ show_ids_in_file($options, $configuration, $file, $filename, $id_regexp);
+ } else {
+ grep_log_file($options, $configuration, $file, $filename, $id_regexp);
+ }
+}
+
+sub scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ if (@$log_filenames) {
+ foreach my $log_filename (@$log_filenames) {
+ $log_filename = 'stdin' if $log_filename eq '-';
+ if (@$log_filenames >= 2) {
+ print "\n" unless $log_filename eq $log_filenames->[0];
+ my $filename_header = "==> $log_filename <==\n";
+ $filename_header = Term::ANSIColor::colored($filename_header,
+ $configuration->{COLORS}->{FILE_HEADER})
+ if $options->{COLORIZE_OUTPUT};
+ print $filename_header;
+ }
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+ } else {
+ my $log_filename = 'stdin';
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+}
+
+sub redirect_and_scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ my $pager;
+
+ my $pid = open($pager, '|-', $configuration->{PAGER}, $configuration->{PAGER_FLAGS});
+ fail_with_error('failed to redirect to pager ', quote_literal($configuration->{PAGER}),
+ ' with flags ', quote_literal($configuration->{PAGER_FLAGS}),
+ ": $OS_ERROR")
+ unless defined $pid;
+ my $stdout = select $pager;
+
+ $pager->autoflush;
+ scan_files($options, $configuration, $id_regexp, $log_filenames);
+
+ close $pager or issue_warning "error occurred while closing the pager (pid: $pid) pipe: $OS_ERROR";
+ select $stdout;
+}
+
+########################################################################
+
+my $configuration_key_map = {
+ 'id-format' => 'ID_INLINE_FORMAT',
+ 'id-indent' => 'ID_INDENT',
+ 'id-heading' => 'PRINT_ID_AS_HEADING',
+ 'id-heading-format' => 'ID_HEADING_FORMAT',
+ 'id-max-length' => 'ID_MAX_LENGTH',
+ 'line-number-format' => 'LINE_NUMBER_FORMAT',
+ 'log-line-number-format' => 'LOG_LINE_NUMBER_FORMAT',
+ 'page-number-format' => 'PAGE_NUMBER_FORMAT',
+
+ 'file-header-color' => 'FILE_HEADER',
+ 'fill-state-color' => 'FILL_STATE',
+ 'first-vbox-color' => 'FIRST_VBOX',
+ 'font-spec-color' => 'FONT_SPEC',
+ 'horizontal-break-candidate-color' => 'HORIZONTAL_BREAK_CANDIDATE',
+ 'horizontal-breakpoint-color' => 'HORIZONTAL_BREAKPOINT',
+ 'id-color' => 'ID_COLOR',
+ 'id-heading-color' => 'ID_HEADING_COLOR',
+ 'line-break-pass-color' => 'LINE_BREAK_PASS',
+ 'line-number-color' => 'LINE_NUMBER',
+ 'log-line-number-color' => 'LOG_LINE_NUMBER',
+ 'math-color' => 'MATH',
+ 'page-number-color' => 'PAGE_NUMBER',
+ 'pager' => 'PAGER',
+ 'pager-flags' => 'PAGER_FLAGS',
+ 'tightness-color' => 'TIGHTNESS',
+ 'vertical-breakpoint-color' => 'VERTICAL_BREAKPOINT'
+};
+
+my $default_configuration = {
+ COLORS => {
+ FILE_HEADER => 'bold black',
+ FILL_STATE => 'bold magenta',
+ FIRST_VBOX => 'bold red',
+ FONT_SPEC => 'grey12',
+ HORIZONTAL_BREAKPOINT => 'bold green',
+ HORIZONTAL_BREAK_CANDIDATE => 'blue',
+ ID_COLOR => 'white on_black',
+ ID_HEADING_COLOR => 'white on_black',
+ LINE_BREAK_PASS => 'bold green',
+ LINE_NUMBER => 'bold black',
+ LOG_LINE_NUMBER => 'italic black',
+ MATH => 'yellow',
+ PAGE_NUMBER => 'bold white on_red',
+ TIGHTNESS => 'bold cyan',
+ VERTICAL_BREAKPOINT => 'red'
+ },
+ ID_INLINE_FORMAT => '%s:',
+ ID_HEADING_FORMAT => '--> %s <--',
+ ID_INDENT => 8,
+ ID_MAX_LENGTH => 40,
+ LINE_NUMBER_FORMAT => '%5d',
+ LOG_LINE_NUMBER_FORMAT => '%6d',
+ PAGE_NUMBER_FORMAT => '[%3d]',
+ PAGER => 'less',
+ PAGER_FLAGS => '--quit-if-one-screen',
+ PRINT_ID_AS_HEADING => 0
+};
+
+sub initialize_highlighting_from_configuration {
+ my $configuration = shift;
+
+ while (my (undef, $assoc) = each %$highlight_patterns) {
+ while (my ($name, $pattern_color_pair) = each %$assoc) {
+ $pattern_color_pair->[1] = $configuration->{COLORS}->{$name};
+ }
+ }
+}
+
+sub modify_configuration {
+ my ($configuration, $key, $value) = @_;
+
+ fail_with_error('malformed KEY=VALUE pair -- missing key') unless $key;
+
+ if (defined $configuration_key_map->{$key}) {
+ if ($key =~ m/-color$/) {
+ $configuration->{COLORS}->{$configuration_key_map->{$key}} = $value;
+ } else {
+ $configuration->{$configuration_key_map->{$key}} = $value;
+ }
+ } else {
+ fail_with_error("@{[quote_literal($key)]} is not a valid configuration KEY");
+ }
+}
+
+sub setup_configuation {
+ my ($config_spec, $configuration) = @_;
+
+ foreach my $spec (split ':', $config_spec) {
+ my ($key, $value) = split '=', $spec;
+ modify_configuration($configuration, $key, $value);
+ }
+}
+
+my $default_options = {
+ COLORIZE_MODE => 'auto',
+ DEBUG => 0,
+ ID => 0,
+ IGNORE_CASE => 0,
+ JOB_NAME => 0,
+ LINE_NUMBER => 0,
+ LOG_LINE_NUMBER => 0,
+ PAGE_NUMBER => 0,
+ REQUEST_PAGER => 1,
+ WORD_REGEXP => 0
+};
+
+sub show_help {
+ print <<HELP_TEXT;
+Usage: @{[COMMAND_NAME]} [OPTION] ID-REGEXP LOG-FILE...
+Structured grep for typog-inspect elements that match ID-REGEXP in LOG-FILE.
+
+Options
+ --color [WHEN],
+ --colour [WHEN] use color to highlight specific log contents
+ WHEN is 'always', 'never', or 'auto'
+ -C, --config KEY=VALUE set configuration KEY to VALUE
+ -i, --[no-]id print matching id with output lines
+ -y, --[no-]ignore-case ignore case distinctions in patterns and data
+ -j, --[no-]job-name print \\jobname with output lines
+ -n, --[no-]line-number print TeX-source line number with output lines
+ -N, --[no-]log-line-number print log-file line number with output lines
+ -p, --[no-]page-number print page number with output lines
+ -P, --[no-]pager redirect output to pager
+ -w, --[no-]word-regexp match only whole words
+
+ -a, --all, --any show all IDs in LOG-FILE
+ --debug turn on debug output
+ -h, --help display this help and exit
+ --show-config show default configuration and exit
+ -V, --version show version information and exit
+
+HELP_TEXT
+
+ exit 0;
+}
+
+sub show_configuration {
+ my $format_string_value = sub {quote_literal($default_configuration->{$_[0]})};
+
+ print <<FIXED_CONFIGURATION_TEXT;
+Configuration
+Key Default Value
+------------------------------------ -------------
+id-format @{[$format_string_value->('ID_INLINE_FORMAT')]}
+id-heading $default_configuration->{PRINT_ID_AS_HEADING}
+id-heading-format @{[$format_string_value->('ID_HEADING_FORMAT')]}
+id-indent $default_configuration->{ID_INDENT}
+id-max-length $default_configuration->{ID_MAX_LENGTH}
+line-number-format @{[$format_string_value->('LINE_NUMBER_FORMAT')]}
+log-line-number-format @{[$format_string_value->('LOG_LINE_NUMBER_FORMAT')]}
+page-number-format @{[$format_string_value->('PAGE_NUMBER_FORMAT')]}
+pager @{[$format_string_value->('PAGER')]}
+pager-flags @{[$format_string_value->('PAGER_FLAGS')]}
+
+FIXED_CONFIGURATION_TEXT
+
+ foreach my $configuration_key (sort keys %$configuration_key_map) {
+ next unless $configuration_key =~ m/-color$/;
+ printf("%-36s %s\n",
+ $configuration_key,
+ quote_literal($default_configuration->
+ {COLORS}->
+ {$configuration_key_map->{$configuration_key}}));
+ }
+
+ exit 0;
+}
+
+sub show_version {
+ print <<VERSION_TEXT;
+typog-grep 0.1
+
+Copyright (C) 2024 by Ch. L. Spiel
+License LPPL: LaTeX Project Public License version 1.3 or later
+VERSION_TEXT
+
+ exit 0;
+}
+
+sub get_options {
+ my ($options, $configuration) = @_;
+
+ Getopt::Long::Configure('gnu_getopt', 'no_ignore_case');
+
+ Getopt::Long::GetOptions('a|all|any' => \$options->{SHOW_ALL_IDS},
+ 'color|colour=s' => \$options->{COLORIZE_MODE},
+ 'C|configuration=s' => sub{setup_configuation($_[1], $configuration)},
+ 'debug+' => \$DEBUG,
+ 'h|help' => \&show_help,
+ 'i|id!' => \$options->{ID},
+ 'y|ignore-case!' => \$options->{IGNORE_CASE},
+ 'j|job-name!' => \$options->{JOB_NAME},
+ 'n|line-number!' => \$options->{LINE_NUMBER},
+ 'N|log-line-number!' => \$options->{LOG_LINE_NUMBER},
+ 'p|page-number!' => \$options->{PAGE_NUMBER},
+ 'P|pager!' => \$options->{REQUEST_PAGER},
+ 'show-config' => \&show_configuration,
+ 'V|version' => \&show_version,
+ 'w|word-regexp!' => \$options->{WORD_REGEXP}) or
+ fail_with_error('problems while parsing options');
+
+ fail_with_error("unknown colorize mode @{[quote_literal($options->{COLORIZE_MODE})]}")
+ unless $options->{COLORIZE_MODE} =~ m/^(?:always|auto|never)$/i
+}
+
+sub do_colorize {
+ my $colorize_mode = shift;
+
+ if ($colorize_mode =~ m/never/i) {
+ 0;
+ } elsif ($colorize_mode =~ m/always/i) {
+ 1;
+ } elsif ($colorize_mode =~ m/auto/i) {
+ not $OUTPUT_IS_REDIRECTED;
+ }
+}
+
+## For the comparison with the POSIX spec of grep(1) consult
+## https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
+
+sub main {
+ $OUTPUT_IS_REDIRECTED = -t STDOUT ? 0 : 1;
+
+ my $options = {%$default_options};
+ my $configuration = {%$default_configuration};
+
+ get_options($options, $configuration);
+ $options->{COLORIZE_OUTPUT} = do_colorize($options->{COLORIZE_MODE});
+ initialize_highlighting_from_configuration($configuration);
+ debug_print(Data::Dumper::Dumper($configuration));
+ debug_print(Data::Dumper::Dumper($options));
+
+ my $id_regexp;
+ if ($options->{SHOW_ALL_IDS}) {
+ $id_regexp = '^';
+ issue_warning("option @{[quote_literal('--id')]} ignored in @{[quote_literal('--all')]} mode")
+ if $options->{ID};
+ } else {
+ fail_with_error('missing ID-REGEXP') unless @ARGV >= 1;
+ $id_regexp = shift @ARGV;
+ }
+
+ if ($options->{REQUEST_PAGER} && $OUTPUT_IS_REDIRECTED) {
+ issue_warning("option @{[quote_literal('--pager')]} ignored because output is redirected");
+ }
+ my $use_pager = $options->{REQUEST_PAGER} && !$OUTPUT_IS_REDIRECTED;
+ if ($use_pager) {
+ redirect_and_scan_files($options, $configuration, $id_regexp, \@ARGV);
+ } else {
+ scan_files($options, $configuration, $id_regexp, \@ARGV);
+ }
+
+ exit ($MATCH_COUNT == 0);
+}
+
+main();
diff --git a/Master/texmf-dist/source/latex/typog/Makefile b/Master/texmf-dist/source/latex/typog/Makefile
new file mode 100644
index 00000000000..bb3c83ab24b
--- /dev/null
+++ b/Master/texmf-dist/source/latex/typog/Makefile
@@ -0,0 +1,302 @@
+### name: Makefile
+### synopsis: Build `typog' style file, tools, and documentation
+### author: Dr. Christoph L. Spiel
+### GNU make version: 4.3
+
+
+SHELL := /bin/sh
+
+
+LATEX := /usr/bin/env max_print_line=2147483647 pdflatex
+LATEX_FLAGS := -file-line-error -halt-on-error -interaction=nonstopmode
+LATEX_RERUN_TRIGGER := '^Package rerunfilecheck Warning: File [^ ]* has changed'
+LATEX_WARNING := '^LaTeX (|[A-Za-z0-9_]* )Warning:'
+
+MAKEINDEX := makeindex
+MAKEINDEX_FLAGS := -q
+
+
+METAPOST := mpost
+METAPOST_FLAGS := -file-line-error -interaction=nonstopmode -tex=latex
+
+
+PODCHECKER := podchecker
+PODCHECKER_FLAGS := -warnings
+
+
+POD2MAN := pod2man
+POD2MAN_FLAGS := $$(sed -ne 's,\\ProvidesPackage{typog}\[\([0-9][0-9]*/[0-9][0-9]*/[0-9][0-9]*\) *v\([^ ]*\) .*$$,--date=\1 --release=\2,p' < typog.sty)
+
+
+POD2TEXI := pod2texi
+POD2TEXI_FLAGS :=
+
+
+GROFF := groff
+## Codes of serif fonts that work for PDF output
+## BM: URW Bookman L
+## N: URW Century Schoolbook L
+## P: URW Palladio L
+## T: URW Nimbus Roman No9 L
+GROFF_FLAGS := -Tpdf -dpaper=a4 -fP -man -wall
+
+
+SPELLCHECK := aspell
+SPELLCHECK_FLAGS := \
+ --add-tex-command='citenum p' --add-tex-command='code p' \
+ --add-tex-command='Cref p' --add-tex-command='cref p' \
+ --add-tex-command='cs p' \
+ --add-tex-command='DescribeEnv p' --add-tex-command='DescribeMacro p' \
+ --add-tex-command='marg p' --add-tex-command='meta p' \
+ --add-tex-command='oarg p' \
+ --lang=en_US --mode=tex
+
+
+SOURCE_FILES := LICENSE Makefile typog.dtx typog.ins
+
+
+
+.PHONY: all
+all: sty pdf man
+
+
+.PHONY: sty
+sty: typog.sty
+
+
+.PHONY: pdf
+pdf: doc ex nomt
+
+
+.PHONY: doc
+doc: typog.pdf
+
+
+.PHONY: ex
+ex: typog-example.pdf
+
+
+.PHONY: nomt
+nomt: typog-nomt.pdf
+
+
+.PHONY: man
+man: typog-grep.1
+
+
+.PHONY: cpio
+cpio:
+ cd ..; \
+ echo $(addprefix typog/,$(SOURCE_FILES)) | \
+ cpio -o | \
+ gzip > "typog-$$(date +%Y-%m-%d).cpio.gz"
+
+
+.PHONY: tar
+tar:
+ cd ..; \
+ tar czf "typog-$$(date +%Y-%m-%d).tar.gz" $(addprefix typog/,$(SOURCE_FILES))
+
+
+.PHONY: clean
+clean:
+ $(RM) ./*.1 ./*.aux ./*.brf ./*.glg ./*.glo ./*.gls
+ $(RM) ./*.hd ./*.idx ./*.ilg ./*.ind ./*.loe ./*.lof ./*.log ./*.lot
+ $(RM) ./*.mps ./*.mpx ./*.out ./*.pdf ./*.toc
+ $(RM) mptextmp.* mpxerr.tex
+ $(RM) README README.html RELEASE-HOWTO RELEASE-HOWTO.html
+
+
+.PHONY: mostlyclean
+mostlyclean: clean
+
+
+.PHONY: maintainer-clean
+maintainer-clean: mostlyclean
+ $(RM) ./*.ist ./*.mp ./*.pl ./*.pod ./*.sed ./*.sty ./*.tex
+
+
+.PHONY: tool-check
+tool-check:
+ @printf '*** LATEX = "%s"\n' '$(LATEX)'
+ $(LATEX) --version
+ @printf '\n\n*** MAKEINDEX = "%s"\n' '$(MAKEINDEX)'
+ $(MAKEINDEX) < /dev/null
+ @printf '\n\n*** METAPOST = "%s"\n' '$(METAPOST)'
+ $(METAPOST) --version
+ @printf '\n*** POD2MAN = "%s"\n' '$(POD2MAN)'
+ $(POD2MAN) --help > /dev/null
+ @printf '\n\n*** POD2TEXI = "%s"\n' '$(POD2TEXI)'
+ $(POD2TEXI) --version
+ @printf '\n\nTool check passed.\n'
+
+
+.PHONY: spell-check
+spell-check:
+ @sed -e '\#<DISABLE-SPELL-CHECK/>#d' \
+ -e '\#<DISABLE-SPELL-CHECK>#,\#</DISABLE-SPELL-CHECK>#d' < typog.dtx | \
+ sed -e 's/^ *%%*//' | \
+ sed -e 's/\\-//g' -e 's/|[^|]*|/ /g' | \
+ $(SPELLCHECK) $(SPELLCHECK_FLAGS) list | \
+ sort | uniq | fmt | sed -e 's/ / /g'
+
+
+.PHONY: update-docs
+update-docs: doc ex typog-grep.1.pdf
+ cp -f typog.pdf typog-example.pdf typog-grep.1 typog-grep.1.pdf docs
+
+
+define HELP_SCREEN
+Selected Phony Targets
+----------------------
+all: Make everything there is to make. This is the .DEFAULT_GOAL.
+
+clean: Remove some products.
+
+cpio: In the parent directory create a cpio(1) archive of the
+ project source files whose name is time-stamped.
+
+doc: Build "typog.pdf" the Typog documentation.
+
+ex: Build "typog-example.pdf" an example and test file for Typog.
+
+maintainer-clean: Remove every product file that can be rebuilt even
+ if uncommon tools are necessary.
+
+mostlyclean: Remove some more products than clean:.
+
+pdf: Build doc: and gauge:.
+
+sty: Only extract "typog.sty" from "typog.dtx". This
+ operation requires LaTeX (-> $(LATEX)) and nothing else.
+
+tar: In the parent directory create a tar(1) file of the project
+ source files whose name is time-stamped.
+
+tool-check: Check whether some of the required tools to build the
+ project are available.
+
+
+Selected Implicit Rules
+-----------------------
+%.pdf: %.dtx
+ Run LaTeX or pdfLaTeX (-> $(LATEX)) on dtx source until a
+ fix-point is reached.
+
+%.pdf: %.tex
+ Run LaTeX or pdfLaTeX (-> $(LATEX)) on tex file until a
+ fix-point is reached.
+
+%.1: %.pod
+ Create a manual page from plain old documentation format.
+ Requires podchecker (-> $(PODCHECKER)) and pod2man
+ (-> $(POD2MAN)).
+
+%.1.pdf: %.1
+ Convert a manual page into a pdf file. Requires groff
+ (-> $(GROFF)).
+
+
+Some Explicit Rules
+-------------------
+README.html:
+ Convert "README.md" to html. Requires markdown(1).
+
+README: Convert "README.html" to plain text. Requires w3m(1).
+
+endef
+
+.PHONY: help
+help:
+ $(info $(HELP_SCREEN))
+
+
+
+.PRECIOUS: %.mps
+
+
+
+define MAKE_INDEX_AND_GLOSSARY
+sed -e '/@/d' -e 's/{\\ttfamily /{\\ttfamily\\hskip0pt\\relax /' < $*.idx > ,$*.idx; \
+mv ,$*.idx $*.idx; \
+$(MAKEINDEX) $(MAKEINDEX_FLAGS) -s typog.ist -t $*.ilg -o $*.ind $*.idx; \
+$(MAKEINDEX) $(MAKEINDEX_FLAGS) -s gglo.ist -t $*.glg -o $*.gls $*.glo
+endef
+
+define GREP_LATEX_WARNINGS
+test -e $*.log && grep -E $(LATEX_WARNING) $*.log | uniq
+endef
+
+%.pdf: %.dtx
+ $(RM) ./$*.aux ./$*.ind ./$*.idx ./$*.gls ./$*.glo ./$*.lot ./$*.toc
+ $(LATEX) $(LATEX_FLAGS) -draftmode $<
+ $(MAKE_INDEX_AND_GLOSSARY)
+ $(LATEX) $(LATEX_FLAGS) $<
+ $(MAKE_INDEX_AND_GLOSSARY)
+ while test -e $*.log && grep -q $(LATEX_RERUN_TRIGGER) $*.log; \
+ do \
+ $(LATEX) $(LATEX_FLAGS) $<; \
+ $(MAKE_INDEX_AND_GLOSSARY); \
+ done
+ $(GREP_LATEX_WARNINGS)
+
+
+%.pdf: %.tex
+ $(RM) ./$*.aux ./$*.ind ./$*.idx ./$*.lot ./$*.toc
+ $(LATEX) $(LATEX_FLAGS) -draftmode $<
+ $(LATEX) $(LATEX_FLAGS) $<
+ while test -e $*.log && grep -q $(LATEX_RERUN_TRIGGER) $*.log; \
+ do \
+ $(LATEX) $(LATEX_FLAGS) $<; \
+ done
+ $(GREP_LATEX_WARNINGS)
+
+
+%-1.mps %-2.mps %-3.mps %-4.mps: %.mp
+ $(METAPOST) -s 'outputtemplate="%j-%c.mps"' $(METAPOST_FLAGS) $<
+
+
+%.1: %.pod
+ $(PODCHECKER) $(PODCHECKER_FLAGS) $<
+ $(POD2MAN) $(POD2MAN_FLAGS) $< $@
+
+%.1.pdf: %.1
+ $(GROFF) $(GROFF_FLAGS) ./$< > $@
+
+%.tex: %.pod | teximan2latex.sed
+ $(POD2TEXI) $(POD2TEXI_FLAGS) ./$< | sed -f teximan2latex.sed > $@
+
+
+%.html: %.md
+ markdown $< > $@
+
+%: %.html
+ w3m -cols 79 $< > $@
+
+
+crooked-paragraphs.mp slant-angle.mp smooth-parshapes.mp title.mp \
+teximan2latex.sed \
+typog-grep.pl typog-grep typog-grep.pod \
+typog.sty typog.ist typog-example.tex typog-nomt.tex: \
+ typog.ins typog.dtx
+ $(LATEX) $(LATEX_FLAGS) $<
+ chmod 755 typog-grep.pl
+ ln -sf typog-grep.pl typog-grep
+
+
+crooked-paragraphs-1.mps crooked-paragraphs-2.mps \
+crooked-paragraphs-3.mps crooked-paragraphs-4.mps: crooked-paragraphs.mp
+
+smooth-parshapes-1.mps smooth-parshapes-2.mps smooth-parshapes-3.mps: smooth-parshapes.mp
+
+slant-angle-1.mps: slant-angle.mp
+
+title-1.mps: title.mp
+
+typog.pdf: typog.dtx \
+ crooked-paragraphs-1.mps crooked-paragraphs-2.mps \
+ crooked-paragraphs-3.mps crooked-paragraphs-4.mps \
+ slant-angle-1.mps title-1.mps \
+ smooth-parshapes-1.mps smooth-parshapes-2.mps smooth-parshapes-3.mps \
+ typog-grep.tex \
+ | typog.sty
diff --git a/Master/texmf-dist/source/latex/typog/typog.dtx b/Master/texmf-dist/source/latex/typog/typog.dtx
new file mode 100644
index 00000000000..0f2176206a2
--- /dev/null
+++ b/Master/texmf-dist/source/latex/typog/typog.dtx
@@ -0,0 +1,9974 @@
+% \iffalse
+%
+% Copyright (C) 2024 by Ch. L. Spiel
+%
+% This work may be distributed and/or modified under the conditions
+% of the LaTeX Project Public License, either version 1.3 of this
+% license or (at your option) any later version. The latest version
+% of this license is in
+% http://www.latex-project.org/lppl.txt
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2003/12/01 or later.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\documentclass{ltxdoc}
+
+\tracingonline=0
+
+%--\OnlyDescription
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+
+
+\PassOptionsToClass{a4paper}{article}
+\PassOptionsToPackage{hyperfootnotes=false}{hyperref}
+\PassOptionsToPackage{charter, scale=1.06}{newtxmath}
+\PassOptionsToPackage{dvipsnames}{xcolor}
+
+\usepackage{amsmath}
+\usepackage{amssymb}
+\usepackage{array}
+\usepackage{booktabs}
+\usepackage{caption}
+\usepackage{dtk-logos}
+\usepackage{enumitem}
+\usepackage{etoolbox}%--\tracingpatches
+\usepackage{fancyhdr}
+\usepackage[T1]{fontenc}
+\usepackage{fullwidth}
+\usepackage{hypdoc}
+\usepackage{hyphenat}
+\usepackage[shrink=10, stretch=10]{microtype}
+\usepackage{multirow}
+\usepackage{needspace}
+\usepackage{placeins}
+\usepackage{ragged2e}
+\usepackage{setspace}
+\usepackage{sidecap}
+\usepackage{tabularx}
+\usepackage{tcolorbox}
+\usepackage{titlesec}\renewcommand*{\bottomtitlespace}{.15\textheight}%nobottomtitles*
+\usepackage[debug, raise*=.05em]{typog}
+\usepackage{xcolor}
+
+
+\usepackage[default, lining, proportional, regular, semibold]{sourceserifpro}
+\usepackage[lining, proportional, regular, semibold]{sourcesanspro}
+\usepackage[lining, regular]{sourcecodepro}
+\usepackage[xcharter]{newtxmath}
+\setbaselineskip{12.5pt}
+
+\makeatletter
+\def\@get@fontclan#1-#2\relax{#1}
+\newcommand*{\fontclan}{\expandafter\@get@fontclan\f@family\relax}
+\makeatother
+
+\newcommand*{\proportionalliningfigures}{\fontfamily{\fontclan-LF}\selectfont}
+\newcommand*{\proportionaloldstylefigures}{\fontfamily{\fontclan-OsF}\selectfont}
+\newcommand*{\tabularliningfigures}{\fontfamily{\fontclan-TLF}\selectfont}
+\newcommand*{\tabularoldstylefigures}{\fontfamily{\fontclan-TOsF}\selectfont}
+
+\newcommand*{\textdenominator}[1]{{\fontfamily{\fontclan-Dnom}\selectfont #1}}
+\newcommand*{\textinferior}[1]{{\fontfamily{\fontclan-Inf}\selectfont #1}}
+\newcommand*{\textnumerator}[1]{{\fontfamily{\fontclan-Numr}\selectfont #1}}
+\newcommand*{\textsuperior}[1]{{\fontfamily{\fontclan-Sup}\selectfont #1}}
+
+\newcommand*{\nativetextfraction}[2]
+ {\mbox{\textnumerator{#1}\textfractionsolidus\textdenominator{#2}}}
+
+\makeatletter
+\renewcommand*{\@makefnmark}{\hbox{\sf\textsuperior{\@thefnmark}}}
+\newenvironment*{tabfigures}
+ {\edef\rmdefault{\fontclan-T\sourceserifpro@figurestyle}\rm\ignorespaces}
+ {\ignorespacesafterend}
+
+\newcommand*{\elseries}{\def\mdseries@rm{el}\def\mdseries@sf{el}\def\mdseries@tt{el}}
+\newcommand*{\textel}[1]{{\elseries\textmd{#1}}}
+\newcommand*{\lseries}{\def\mdseries@rm{l}\def\mdseries@sf{l}\def\mdseries@tt{l}}
+\newcommand*{\textl}[1]{{\lseries\textmd{#1}}}
+%%--\newcommand*{\mdseries}{\def\mdseries@rm{m}\def\mdseries@sf{m}\def\mdseries@tt{m}}
+%%--\newcommand*{\textmd}[1]{{\mdseries\textmd{#1}}}
+\newcommand*{\sbseries}{\def\bfseries@rm{sb}\def\bfseries@sf{sb}\def\bfseries@tt{sb}}
+\newcommand*{\textsb}[1]{{\sbseries\textbf{#1}}}
+\newcommand*{\bseries}{\def\bfseries@rm{b}\def\bfseries@sf{b}\def\bfseries@tt{b}}
+\newcommand*{\textb}[1]{{\bseries\textbf{#1}}}
+\newcommand*{\ebseries}{\def\bfseries@rm{k}\def\bfseries@sf{eb}\def\bfseries@tt{k}}
+\newcommand*{\texteb}[1]{{\ebseries\textbf{#1}}}
+\makeatother
+
+
+\usepackage{cleveref}
+
+
+\expandafter\GetFileInfo\expandafter{\jobname.sty}
+\def\aspdfdate#1/#2/#3\relax{D:#1#2#3}
+\edef\pdffiledate{\expandafter\aspdfdate\filedate\relax}
+
+\hypersetup{
+ citecolor = blue,
+ colorlinks = true,
+ linkcolor = blue,
+ linktocpage = false,
+ pdfauthor={Dr. Christoph L. Spiel},
+ pdfcreationdate={\pdffiledate},
+ pdfkeywords={LaTeX, typography, ligature, italic-correction, paragraph justification, baselineskip, sloppy, ragged},
+ pdflang=en-US,
+ pdfsubject={Typographic fine-tuning for LaTeX},
+ pdftitle={Package typog \fileversion},
+ raiselinks = false,
+ urlcolor = [rgb]{0, 0, .5}% = navy
+}
+
+
+\makeatletter
+\renewcommand*{\@dotsep}{10000} % suppress leaders
+\patchcmd{\@dottedtocline}{\normalfont}{\bfseries}{\relax}{\PatchingFailed}
+\makeatother
+
+
+\Crefname{figure}{Figure}{Figures}
+\crefname{figure}{Fig.}{Figs.}
+
+\Crefname{page}{Page}{Pages}
+\crefname{page}{p.}{p.}
+
+\Crefname{section}{Section}{Sections}
+\crefname{section}{Sec.}{Secs.}
+
+\Crefname{table}{Table}{Tables}
+\crefname{table}{Tab.}{Tabs.}
+
+
+\DeclareCaptionJustification{centerlastjustification}{\justify\fussy\lastlinecenteredpar}
+\DeclareCaptionJustification{smoothraggedjustification}%
+ {\renewcommand*{\smoothraggedrightgenerator}{quintuplet}%
+ \setlength{\smoothraggedrightragwidth}{1em}%
+ \smoothraggedrightpar\relax}
+\DeclareCaptionJustification{relaxedjustification}{\justify\slightlysloppy}
+
+\newcommand*{\floatcaptionwidth}{.79\textwidth}
+
+\captionsetup[figure]{font=small, justification=centerlastjustification,
+ labelfont=sc, width=\floatcaptionwidth}
+\captionsetup[table]{font=small, justification=centerlastjustification,
+ labelfont=sc, width=\floatcaptionwidth}
+\captionsetup[SCfigure]{font=small, justification=relaxedjustification,
+ labelfont=sc}
+\captionsetup[SCtable]{font=small, justification=relaxedjustification,
+ labelfont=sc}
+
+
+\newsavebox{\listlabelbox}
+
+\sbox{\listlabelbox}{---}
+\SetEnumitemKey{noindent}{
+ label={---},
+ labelwidth=\wd\listlabelbox,
+ leftmargin=!
+}
+
+
+\SetEnumitemKey{nestedinspecialsection}{
+ leftmargin=10pt
+}
+
+\SetEnumitemKey{notopsep}{
+ after=\vskip.8em plus .2em minus .4em,
+ partopsep=0pt,
+ topsep=0pt
+}
+
+
+\newlength{\marginindicatorsep}
+\setlength{\marginindicatorsep}{10pt}
+
+\newcommand*{\marginalizesectionnumber}[1]
+ {\makebox[0pt][r]{#1\hspace{\marginindicatorsep}}}
+
+
+\fancypagestyle{pagenumberonly}{
+ \fancyhead[L]{}
+ \fancyhead[R]{\thepage}
+}
+\pagestyle{fancy}
+\fancyhf{}
+\fancyhead[L]{\rightmark}
+\fancyhead[R]{\thepage}
+\newcommand*{\resetfancyhead}
+ {\fancyhead[L]{\textsf{\textsc{\textls[20]{\nouppercase\rightmark}}}}}
+
+\renewcommand*{\headrulewidth}{0pt}
+\renewcommand*{\sectionmark}[1]
+ {\def\truesectionname{#1}%
+ \markright{\textsf{\marginalizesectionnumber{\thesection}%
+ \textsc{\textls[20]{#1}}}}}
+\renewcommand*{\subsectionmark}[1]
+ {\markright{\textsf{\marginalizesectionnumber{\thesubsection}%
+ \textsc{\textls[20]{\truesectionname:\enspace}}#1}}}
+
+
+\titleformat{\section}[hang]
+ {\sffamily\Large\bfseries}{\marginalizesectionnumber{\thesection}}{0pt}{}
+\titleformat{\subsection}[hang]
+ {\sffamily\large\bfseries}{\marginalizesectionnumber{\thesubsection}}{0pt}{}
+\titleformat{\subsubsection}[hang]
+ {\sffamily\normalsize\bfseries}{\marginalizesectionnumber{\thesubsubsection}}{0pt}{}
+\titleformat{\paragraph}[runin]
+ {\sffamily\normalsize\bfseries}{\theparagraph}{1em}{}
+
+
+\let\footnoterule=\relax% suppress footnote rule
+
+\makeatletter
+\renewcommand*{\@makefntext}[1]
+ {\noindent
+ \llap{\let\@textsuperscript=\relax% use "normal" figures for the footnote numbers
+ \let\textsuperior=\relax
+ \@makefnmark
+ \hspace{\marginindicatorsep}}% separate the footnote number and the body
+ #1}
+\makeatother
+
+
+\pretocmd{\DescribeEnv}{\needspace{25pt}}{\relax}{\PrependingFailed}
+\pretocmd{\DescribeMacro}{\needspace{25pt}}{\relax}{\PrependingFailed}
+
+
+\setlength{\skip\footins}{25pt}
+\setlength{\overfullrule}{3pt}
+\renewcommand*{\sidecaptionsep}{16pt}
+
+
+
+\newrobustcmd*{\acronym}[1]{\mbox{\scshape\MakeLowercase{#1}}}
+
+\newcommand*{\application}[1]{\mbox{\sffamily #1}}
+
+\renewcommand*{\arraystretch}{1.12}
+
+\newcommand*{\bibauthor}[1]{\mbox{\textsc{#1}}}
+\newcommand*{\bibtitle}[1]{\textit{#1}}
+\newcommand*{\biburl}[1]{\url{#1}}
+
+\newcommand*{\bottomstrut}{\rule[-.5em]{0pt}{0pt}}
+
+\newenvironment*{codeexample}
+ {\vspace{.5\smallskipamount}
+ \par
+ \centering
+ \begin{minipage}{\linewidth}
+ \ttfamily
+ \begin{tabbing}}
+ {\end{tabbing}
+ \end{minipage}
+ \par
+ \vspace{.5\smallskipamount}}
+
+\makeatletter
+\newcommand*{\citenum}[1]{\@nameuse{b@#1}}
+\makeatother
+
+\def\code#1{\texttt{#1}}
+
+\newrobustcmd*{\command}[1]{\mbox{\textbf{#1}}}
+
+\newcommand*{\doublequotes}[1]{\doubleguillemetright\kern-.03333em #1\doubleguillemetleft}
+
+\newcommand*{\dumpmacro}[1]{\texttt{\detokenize\expandafter{#1}}}
+
+\newcommand*{\filesystem}[1]{\mbox{\textit{#1\/}}}
+
+\newcommand*{\filledrectangle}[2]{\rule{#1}{#2}}
+\newcommand*{\filledsquare}[1]{\filledrectangle{#1}{#1}}
+
+\newcommand*{\foreignphrase}[1]{\textsl{#1}}
+
+\newcommand*{\formatskip}[3]{#1\genfrac{}{}{0pt}{}{{+}#2}{{-}#3}}
+
+\makeatletter
+\renewcommand*{\fps@figure}{htbp}
+\renewcommand*{\fps@table}{htbp}
+\makeatother
+
+\newcommand*{\hollowrectangle}[2]
+ {\setlength{\fboxrule}{.5pt}%
+ \setlength{\fboxsep}{0pt}%
+ \framebox{\rule{#1}{0pt}\rule{0pt}{#2}}}
+\newcommand*{\hollowsquare}[1]{\hollowrectangle{#1}{#1}}
+
+
+\makeatletter
+\apptocmd{\index@prologue}
+ {\marginnote{In the Index page ranges are stuck together with
+ \hyperref[syn:figuredash]{\cs{figuredash*}}.}}
+ {\relax}
+ {\AppendingFailed}
+\makeatother
+
+\newcommand*{\logmacro}[1]
+ {\ifdef{#1}
+ {\message{^^JDump of macro \string#1 follows.^^J}
+ \message{\detokenize\expandafter{#1}}
+ \message{^^JEnd macro dump.^^J}}
+ {\message{^^JMacro \string#1 is not defined.^^J}}}
+
+\newcommand*{\marginnoteformat}
+ {\setstretch{1}%\overfullrule=0pt
+ \sffamily
+ \footnotesize
+ \nofontexpansion
+ \slightlysloppy[1]
+ \loosespacing[1]
+ \setlength{\smoothraggedrightragwidth}{1.5em}
+ \def\smoothraggedrightgenerator{quintuplet}%
+ \smoothraggedrightpar}
+\newcommand*{\marginnote}[1]{\marginpar{\marginnoteformat #1}}
+\addtolength{\marginparpush}{3pt}
+\addtolength{\marginparsep}{25pt}
+\addtolength{\marginparwidth}{-20pt}
+\newcommand*{\shiftedmarginnote}[1]
+ {\marginpar{\moveleft \leftmargin
+ \hbox{\parbox{\dimexpr\marginparwidth - \marginparsep}
+ {\marginnoteformat #1}}}}
+
+\newenvironment*{maxipage}
+ {\fullwidthsetup{leftmargin=-\marginparsep - \marginparwidth,
+ width=\textwidth + \marginparsep + \marginparwidth}%
+ \begin{fullwidth}}
+ {\end{fullwidth}}
+
+\newcommand*{\microtyperequiredmarker}
+ {\mbox{\normalfont\packagename{microtype}~req.}}
+
+\newlength{\emreference}
+\AtBeginDocument{\setlength{\emreference}{\fontdimen6\font}}
+\newrobustcmd*{\milliem}[1]
+ {\ifdim #1=0pt
+ #1%
+ \else
+ \nativetextfraction{\the\numexpr\dimexpr (#1) * 1000 / \emreference}{1000}\:em%
+ \fi}
+
+\newcommand*{\needtocspace}[1][3]
+ {\addtocontents{toc}{\protect\needspace{#1\baselineskip}}}
+
+\newcommand*{\packagename}[1]{\mbox{\textsf{#1}}}
+\newcommand*{\programname}[1]{\mbox{\textbf{#1}}}
+\newcommand*{\propername}[1]{\mbox{\textsc{#1}}}
+
+\newcommand*{\quarterspace}{\hspace{.25em}}
+
+\NewDocumentCommand{\sample}{s m}
+ {\setbox0=\hbox{#2}% H: 6.19849pt, /: 7.49817
+ \mbox{\raisebox{\dimexpr -.15em - \dp0}{\tiny$\llcorner$}%
+ \kern-.15em\copy0\kern-.15em
+ \raisebox{\ifdim\ht0>.7em
+ \ifx#1\BooleanTrue
+ .4em
+ \else
+ \dimexpr\ht0 - .1em
+ \fi
+ \else
+ .4em
+ \fi}
+ {\tiny$\urcorner$}}}
+
+\newcommand*{\sectionfinish}
+ {\vfill
+ {\centering
+ \textcolor{customred4}
+ {\filledsquare{5pt}\enspace\filledsquare{5pt}}%
+ \par}%
+ \vfill}
+\let\sectionfinish=\relax
+
+\newcommand*{\sinceversion}[1]{% modeled after \NewIn of "doc.dtx"
+ \leavevmode
+ \marginpar{\hfill\textcolor{\markercolor}{\sf\scshape\proportionaloldstylefigures #1}}%
+ \ignorespaces
+}
+
+\newcommand*{\singlequotes}[1]{\mbox{\singleguillemetright #1\singleguillemetleft}}
+
+\newcommand*{\specialsectionheading}[1]{\textcolor{\markercolor}{\textit{\textbf{#1}}}}
+\definecolor{customred1}{rgb}{.890, .282, .282}%-- https://paletton.com/
+\definecolor{customred2}{rgb}{.831, .110, .110}
+\definecolor{customred3}{rgb}{.686, .043, .043}
+\definecolor{customred4}{rgb}{.569, .000, .000}
+\definecolor{customred5}{rgb}{.420, .000, .000}
+\newcommand*{\markercolor}{customred4}
+\newcommand*{\specialsectionmarker}{\color{\markercolor}\filledsquare{5pt}}
+\newcommand*{\specialsectionbegin}
+ {\llap{\raisebox{1pt}{\specialsectionmarker}%
+ \hspace{\marginindicatorsep}}}
+\newcommand*{\specialsectionend}
+ {\ifmmode
+ \specialsectionmarker
+ \else
+ \leavevmode
+ \unskip
+ \penalty9999\mbox{}\nobreak
+ \hfill
+ \quad
+ \mbox{\specialsectionmarker}%
+ \fi}
+\newtoggle{printspecialsectionmarker}
+\NewDocumentEnvironment{specialsection}{m m}
+ {\Needspace{4\baselineskip}%
+ \toggletrue{printspecialsectionmarker}%
+ \begin{list}
+ {\specialsectionheading{#1\ifblank{#2}{}{\textup{\space---\space#2}}}}
+ {\itemindent=0pt
+ \labelwidth=10pt
+ \leftmargin=15pt
+ \listparindent=15pt
+ \parsep=0pt
+ \topsep=\medskipamount}
+ \newcommand*{\specialsectionendhere}
+ {\specialsectionend
+ \global\togglefalse{printspecialsectionmarker}}
+ \item
+ \nointerlineskip
+ \leavevmode\par
+ \noindent}
+ {\iftoggle{printspecialsectionmarker}{\specialsectionend}{\relax}%
+ \end{list}}
+
+ \newenvironment*{caution}[1][]{\begin{specialsection}{Caution}{#1}}{\end{specialsection}}
+ \newenvironment*{example}[1][]{\begin{specialsection}{Example}{#1}}{\end{specialsection}}
+ \newenvironment*{futuredirection}[1][]
+ {\begin{specialsection}{Anticipated Changes \& Possible Extensions}{#1}\small}
+ {\end{specialsection}}
+ \newenvironment*{important}[1][]{\begin{specialsection}{Important}{#1}}{\end{specialsection}}
+ \newenvironment*{note}[1][]{\begin{specialsection}{Note}{#1}}{\end{specialsection}}
+ \newenvironment*{notes}[1][]{\begin{specialsection}{Notes}{#1}}{\end{specialsection}}
+ \newenvironment*{tip}[1][]{\begin{specialsection}{Tip}{#1}}{\end{specialsection}}
+ \newenvironment*{tips}[1][]{\begin{specialsection}{Tips}{#1}}{\end{specialsection}}
+ \newenvironment*{usecase}[1][]{\begin{specialsection}{Use Case}{#1}\small}{\end{specialsection}}
+ \newenvironment*{usecases}[1][]{\begin{specialsection}{Use Cases}{#1}\small}{\end{specialsection}}
+
+\newcommand*{\specialcodesectionheading}[1]{\textcolor{\markercolor}{\textbf{\textit{#1}}}}
+\newenvironment*{specialcodesection}[1]
+ {\Needspace{4\baselineskip}%
+ \begin{tcolorbox}[colback=white, colframe=\markercolor,
+ bottomrule=0pt, leftrule=5pt, rightrule=0pt, toprule=0pt]
+ \sf\typogsetupsf
+ \begin{list}
+ {\specialcodesectionheading{#1}}
+ {\itemindent=0pt
+ \labelwidth=20pt
+ \leftmargin=25pt
+ \listparindent=15pt
+ \parsep=0pt
+ \topsep=\medskipamount}
+ \item
+ \nointerlineskip
+ \leavevmode\par
+ \noindent}
+ {\end{list}
+ \end{tcolorbox}}
+ \newenvironment*{anticipatedchange}
+ {\begin{specialcodesection}{Anticipated Change}}
+ {\end{specialcodesection}}
+ \newenvironment*{implementationnote}
+ {\begin{specialcodesection}{Implementation Note}}
+ {\end{specialcodesection}}
+ \newenvironment*{knownbug}
+ {\begin{specialcodesection}{Known Bug}}
+ {\end{specialcodesection}}
+
+\newenvironment*{suspendshortverb}
+ {\DeleteShortVerb{\|}}
+ {\MakeShortVerb{\|}}
+
+\definecolor{cold-silver}{cmyk}{.08, 0, 0, .18}
+\newenvironment*{synopsis}
+ {\begin{tcolorbox}[boxrule=.25pt, colback=cold-silver]%
+ \phantomsection}
+ {\end{tcolorbox}}
+
+\newenvironment*{tablenotes}
+ {\medskip
+ \centering
+ \small
+ \begin{minipage}{\floatcaptionwidth}}
+ {\end{minipage}}
+\newcommand*{\tablenotemark}[1]{\smash{\textsuperscript{#1}}}
+
+\newcommand*{\termparbox}[1]{\parbox[t]{\linewidth}{#1\bottomstrut}}
+
+\newcommand*{\thousandsseparator}{\mbox{,}}
+
+\newcommand*{\topstrut}{\rule{0pt}{1.3em}}
+
+\newcommand*{\typogsetuprm}
+ {\typogsetup{raise*=.025em,
+ raisecapitalguillemets=.05em,
+ raiseguillemets=.03333em,
+ raisefiguredash=.05em}}
+\newcommand*{\typogsetupsf}
+ {\typogsetup{raise*=.06667em,
+ raiseguillemets=.05em}}
+
+\newcommand*{\visualpar}{\textcolor{\markercolor}{\P}\linebreak[1]\enspace}
+
+\newenvironment*{whittyquote}
+ {\begin{flushright}
+ \renewcommand*{\propername}[1]{\mbox{##1}}%
+ \sf\typogsetupsf}
+ {\end{flushright}}
+
+\newenvironment*{widecodeexample}
+ {\begin{maxipage}
+ \flushright
+ \begin{minipage}{\textwidth}
+ \ttfamily
+ \begin{tabbing}}
+ {\end{tabbing}
+ \end{minipage}
+ \end{maxipage}}
+
+
+\NewDocElement[macrolike = true,
+ idxtype = dim.,
+ idxgroup = dimensions,
+ printtype = \textit{dimen}]
+ {LaTeXDimen}{ldimen}
+\pretocmd{\DescribeLaTeXDimen}{\needspace{25pt}}{\relax}{\PrependingFailed}
+
+\NewDocElement[macrolike = false,
+ idxtype = enumitem-key,
+ idxgroup = enumitem-keys,
+ printtype = \textit{enumitem key}]
+ {EnumItemKey}{enumitemkey}
+\pretocmd{\DescribeEnumItemKey}{\needspace{25pt}}{\relax}{\PrependingFailed}
+
+
+\hyphenation{% https://hyphenateit.com/en-us
+ Double-guillemet-left
+ Double-guillemet-right
+ Double-quotes
+ Single-guillemet-left
+ Single-guillemet-right
+ Single-quotes
+ adj-demerits
+ allow-break
+ babel-hyphenation
+ base-line-skip
+ break-penalty
+ breakable-display
+ capital-hyphen
+ capital-times
+ cite-dash
+ club-penalties
+ cref-range-conjunction
+ display-break
+ display-widow-penalties
+ double-guillemet-right
+ double-hyphen-demerits
+ double-quotes
+ ex-hyphen-penalty
+ figure-dash
+ guille-met
+ guille-mets
+ inter-display-line-penalty
+ inter-text
+ kerned-hyphen
+ last-line-centered
+ last-line-centered-par
+ last-line-ragged-left
+ last-line-ragged-left-par
+ line-width
+ loose-ness
+ loose-spacing
+ make-at-letter
+ make-at-other
+ mar-gin-al
+ math-italics-correction
+ micro-type
+ narrow-space
+ narrow-space-scale
+ narrow-space-strength
+ number-dash
+ par-box
+ par-indent
+ parfillskip
+ pdf-string-def-Disable-Commands
+ post-display-penalty
+ pre-display-penalty
+ raise-capital-guillemets
+ raise-capital-hyphen
+ raise-capital-times
+ raise-number-dash
+ set-baseline-skip
+ set-baseline-skip-percentage
+ set-font-expand
+ set-font-shrink
+ set-font-stretch
+ set-leading
+ set-leading-percentage
+ short-inter-text
+ single-guillemet-left
+ single-guillemet-right
+ single-quotes
+ slash-kern
+ slightly-sloppy
+ slightly-sloppy-par
+ sloppy-par
+ smooth-ragged-right-fuzz-factor
+ smooth-ragged-right-par
+ smooth-ragged-right-shape-quintuplet
+ smooth-ragged-right-shape-septuplet
+ smooth-ragged-right-shape-triplet
+ space-skip
+ text-italics-correction
+ tight-spacing
+ tracing-boxes
+ tracing-para-graphs
+ tracking-tt-spacing
+ typog-get
+ typog-setup
+ vtie-bot
+ vtie-bot-disp
+ vtie-bot-disp-par
+ vtie-bot-disp-top-par
+ vtie-bot-par
+ vtie-top
+ vtie-top-par
+ wide-space
+ wide-space-scale
+ wide-space-strength
+ widow-penalties
+}
+
+
+\begin{document}
+ \typogsetuprm
+ \DocInput{typog.dtx}
+\end{document}
+%</driver>
+%<*index-style>
+actual '='
+delim_r "\\figuredash*"
+heading_prefix "\\pagebreak[3]\\smallskip\n\n{\\sffamily\\bfseries\\large "
+heading_suffix "}\\nopagebreak\n"
+headings_flag 1
+level '>'
+quote '!'
+%</index-style>
+% \fi
+%
+%
+% \DoNotIndex{\,}
+% \DoNotIndex{\addtolength,\advance,\aftergroup,\allowdisplaybreaks,\arabic}
+% \DoNotIndex{\AtBeginDocument,\autotransfer}
+% \DoNotIndex{\baselineskip}
+% \DoNotIndex{\c,\char,\clubpenalties,\clubpenalty,\count,\cs,\csname}
+% \DoNotIndex{\DeclareRobustCommand,\def,\define@choicekey,\define@key,\detokenize}
+% \DoNotIndex{\dim,\dimen,\dimexpr,\discretionary,\displaywidowpenalties,\displaywidowpenalty}
+% \DoNotIndex{\edef,\else,\emergencystretch,\empty,\endcsname}
+% \DoNotIndex{\endlastlineflushrightpar}
+% \DoNotIndex{\endlastlineraggedleftpar}
+% \DoNotIndex{\endnofontexpand,\endnofontexpansion}
+% \DoNotIndex{\endsmoothraggedrightshapequintuplet}
+% \DoNotIndex{\endsmoothraggedrightshapeseptuplet}
+% \DoNotIndex{\endsmoothraggedrightshapetriplet}
+% \DoNotIndex{\endtypoginspect}
+% \DoNotIndex{\exhyphenpenalty,\expandafter,\ExplSyntaxOff,\ExplSyntaxOn}
+% \DoNotIndex{\fi,\finalhyphendemerits,\font,\fontdimen,\fp,\fussy,\futurelet}
+% \DoNotIndex{\gdef,\global,\glueexpr,\@gobble}
+% \DoNotIndex{\guillemotleft,\guillemotright,\guilsinglleft,\guilsinglright}
+% \DoNotIndex{\hbadness,\hfuzz,\hskip,\hspace}
+% \DoNotIndex{\ignorespaces,\ignorespacesafterend}
+% \DoNotIndex{\if,\IfBooleanT,\IfBooleanTF,\ifcase,\ifdefined,\ifdim,\iffalse,\ifmmode,\ifMT@expansion}
+% \DoNotIndex{\@ifnextchar,\IfNoValueF,\IfNoValueTF,\ifnum}
+% \DoNotIndex{\iftypog@microtype@loadedfalse}
+% \DoNotIndex{\iftypog@microtype@preloadedfalse}
+% \DoNotIndex{\ifvmode,\ifx,\ignorespaces,\inputlineno,\int,\interlinepenalty}
+% \DoNotIndex{\jobname}
+% \DoNotIndex{\kern}
+% \DoNotIndex{\l,\lastlinefit,\lastlineflushrightpar,\lastlineraggedleftpar,\leftmargin,\leftskip,\let}
+% \DoNotIndex{\linepenalty,\linewidth,\@listdepth,\looseness,\lsstyle}
+% \DoNotIndex{\@M,\m@th,\mathbin,\mathord,\maxdimen,\message,\microtypecontext,\microtypesetup}
+% \DoNotIndex{\@minus,\mkern,\m@ne,\mspace,\MT@letterspace@,\MT@MT,\muexpr}
+% \DoNotIndex{\@ne,\NeedsTeXFormat,\NewDocumentCommand,\NewDocumentEnvironment,\newcommand,\newenvironment}
+% \DoNotIndex{\newcounter,\newdimen,\newif,\newlength,\newmuskip}
+% \DoNotIndex{\nobreak,\nofontexpand,\nofontexpansion,\nr,\numexpr}
+% \DoNotIndex{\or,\optarg}
+% \DoNotIndex{\p@,\PackageError,\PackageWarning}
+% \DoNotIndex{\par,\parfillskip,\parindent,\parshape,\pdf@strcmp}
+% \DoNotIndex{\pdfstringdefDisableCommands}
+% \DoNotIndex{\penalty,\@plus,\PopPostHook,\postdisplaypenalty,\predisplaypenalty,\prg}
+% \DoNotIndex{\pretolerance,\protected,\ProvidesPackage,\PushPostHook}
+% \DoNotIndex{\raisebox,\refstepcounter,\relax,\RenewExpandableDocumentCommand,\RequirePackage,\rightskip}
+% \DoNotIndex{\setcounter,\SetEnumitemKey,\SetExpansion,\setkeys,\setlength,\setstretch}
+% \DoNotIndex{\showboxbreadth,\showboxdepth,\skip,\sloppy}
+% \DoNotIndex{\smoothraggedrightpar}
+% \DoNotIndex{\smoothraggedrightshapequintuplet}
+% \DoNotIndex{\smoothraggedrightshapeseptuplet}
+% \DoNotIndex{\smoothraggedrightshapetriplet}
+% \DoNotIndex{\space,\spaceskip,\stepcounter,\@strength,\string}
+% \DoNotIndex{\textemdash,\textendash,\textsf,\textsl,\texttimes,\textwidth,\the,\times,\tl,\tolerance}
+% \DoNotIndex{\tracingnone,\tracingpages,\tracingparagraphs}
+% \DoNotIndex{\typeout,\typoginspect,\typoglogo}
+% \DoNotIndex{\unless}
+% \DoNotIndex{\val,\value,\vbadness,\vfuzz}
+% \DoNotIndex{\widowpenalties,\widowpenalty}
+% \DoNotIndex{\z@,\z@skip}
+%
+%
+% \changes{v0.1}{2024-3-7}{Initial version.}
+%
+%
+% \pagenumbering{roman}
+%
+% \title{\typoglogo{} \capitalendash{} Typographic Fine\rightkernedhyphen*[20]{-120}Tuning}
+% \author{Ch.~L.~Spiel\footnote{\quarterspace\texttt{cspiel@users.sourceforge.org}}}
+% \date{\fileversion\qquad \filedate}
+% \maketitle
+% \thispagestyle{empty}
+%
+% \begingroup
+% \let\small=\normalsize
+% \begin{abstract}
+% \begin{lastlinecenteredpar}
+% \noindent
+% Package~\packagename{typog} provides macros and environments for
+% \mbox{(micro-)\itcorr{2}}\breakpoint typographic enhancements. It also supplies some
+% means to avoid common typographic problems as, for example, orphan or widow lines.
+% Moreover it supplies high-level front-ends for packages~\packagename{microtype} and
+% \packagename{setspace}.
+% \end{lastlinecenteredpar}
+% \end{abstract}
+% \endgroup
+%
+%
+% \iffalse
+%<*title>
+prologues := 3;
+truecorners := 1;
+linecap := butt;
+
+string roman_font;
+roman_font := "pplr8r"; % URW Palladio L - Roman
+
+string italics_font;
+italics_font := "pplri8r"; % URW Palladio L - Italic
+
+picture dash_dotted;
+dash_dotted := dashpattern(on 3 off 3 on 0 off 3);
+
+u := 280;
+
+font_scale := 20;
+
+pair loc[];
+loc[1] := .2[origin, (u, 0)];
+loc[2] := .5[origin, (u, 0)];
+loc[3] := .8[origin, (u, 0)];
+
+pair slant_vector;
+slant_vector := (63, 150);
+
+pair raise_vector[];
+raise_vector[0] := (0, 44);
+raise_vector[1] := (0, 61);
+raise_vector[2] := (0, 54);
+raise_vector[3] := (0, 71);
+
+
+picture letter_V;
+letter_V := thelabel.top("V" infont roman_font scaled font_scale, loc[1]);
+
+picture normal_hyphen;
+normal_hyphen := thelabel.top("-" infont roman_font scaled font_scale, loc[2] + raise_vector[0]);
+
+picture raised_hyphen;
+raised_hyphen := thelabel.top("-" infont roman_font scaled font_scale, loc[2] + raise_vector[1]);
+
+picture letter_A;
+letter_A := thelabel.top("A" infont roman_font scaled font_scale, loc[3]);
+
+
+beginfig(1);
+ draw letter_V;
+ draw normal_hyphen withcolor .9 white;
+ draw raised_hyphen;
+ draw letter_A;
+
+ pickup pencircle scaled .4pt;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (7, 0) dashed evenly;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (27, 0) dashed evenly;
+ draw (loc[1] -- loc[1] + slant_vector) shifted (80, 0) dashed evenly;
+ draw (loc[3] -- loc[3] + slant_vector) shifted (-68, 0) dashed evenly;
+
+ draw .35[origin, (u, 0)] + raise_vector[2] -- .8[origin, (u, 0)] + raise_vector[2]
+ dashed dash_dotted withcolor .6white;
+ draw .35[origin, (u, 0)] + raise_vector[3] -- .8[origin, (u, 0)] + raise_vector[3]
+ dashed dash_dotted;
+endfig;
+end
+%</title>
+% \fi
+%
+%
+% \vspace*{20pt}
+%
+% \begin{center}
+% \includegraphics{title-1.mps}
+% \end{center}
+%
+% \vfill
+%
+% \begin{lastlinecenteredpar}
+% \footnotesize
+% \noindent
+% This package is copyright \textcopyright~2024 Ch.~L.~Spiel. It may be distributed
+% and\kernedslash*or modified under the conditions of the \LaTeX{} Project Public License
+% \acronym{(LPPL)}, either version~1.3c of this license or --~at your option~-- any later
+% version. This work has the \acronym{LPPL} maintenance status
+% \doublequotes{author-maintained}.
+% \end{lastlinecenteredpar}
+%
+%
+% \clearpage
+% \thispagestyle{pagenumberonly}
+% \tableofcontents
+% \vspace{\fill}
+%
+%
+% \thispagestyle{pagenumberonly}
+% \listoftables
+% \phantomsection
+% \addcontentsline{toc}{subsection}{List of Tables}
+% \vspace{\fill}
+%
+%
+% \begingroup
+% \footnotesize
+% \singlespacing
+% \noindent
+% The font sample on the title page was generated with the help of \MP{} using
+% \doublequotes{\acronym{URW} Palladio~L}\index{font>URW Palladio L=\acronym{URW} Palladio
+% L}.
+% \endgroup
+%
+%
+% \clearpage
+% \pagenumbering{arabic}
+% \section{Introduction}\label{sec:introduction}
+%
+% \begin{whittyquote}
+% \doublequotes{Good typography} is the minimum acceptable solution; \\
+% \doublequotes{fine typography} is what we aspire to. \\
+% \capitalemdash*~\propername{Ilene Strizver}
+% \end{whittyquote}
+%
+% \noindent
+% \LaTeX{} is the beginning of good typesetting -- not the end. This package provides some
+% tools for even better looking documents. When applied correctly its effects appear subtle
+% and inconspicuous.
+%
+%
+% \subsection{Overview}\label{sec:overview}
+%
+% Package~\packagename{typog} focuses on (micro-)typographic improvements.
+%
+% \Cref{sec:information} tends to the wish for more information in the typesetting process
+% whether during the draft phase or in the final printed manuscript.\marginnote{Throughout the
+% whole document we indicate actual uses of the package's features in the margin. All these
+% notes are examples themselves as they are typeset with
+% \hyperref[syn:slightlysloppy]{\code{slightlysloppy}},
+% \hyperref[syn:loosespacing]{\code{loosespacing}}, and
+% \hyperref[syn:smoothraggedrightpar]{\code{smoothraggedrightpar}}.~\visualpar The title page
+% has already demonstrated the effect of
+% \hyperref[syn:lastlinecenteredpar]{\code{lastlinecenteredpar}} in justified paragraphs for
+% the abstract and the copyright notice.}
+%
+% \Cref{sec:latex-hyphenation} expands the hyphenation facilities of \LaTeX.
+%
+% \Cref{sec:break-ligatures,sec:manual-italic-correction,sec:extra-kerning,sec:raise-characters}
+% deal with vertically positioning glyphs in a more pleasant way.
+%
+% \Cref{sec:align-last-line,sec:fill-last-line} discuss dearly missed macros for better control
+% of the last line of a paragraph.
+%
+% \Cref{sec:spacing-control} covers the manipulation of the length of a paragraph.
+%
+% \Cref{sec:microtype-frontend} expounds on the \packagename{microtype} front-end: font
+% tracking~(\ref{sec:tracking-control}), font expansion~(\ref{sec:font-expansion-control}), and
+% character protrusion~(\ref{sec:protrusion}).
+%
+% In \cref{sec:sloppy-paragraphs} we address some shortcomings of spacing control with a
+% replacement for the macro~\cs{sloppy} and the related environment~\code{sloppypar}.
+%
+% \Cref{sec:vtie-paragraph} presents several special functions to avoid club or widow lines in
+% a paragraph.
+%
+% As a simple extension of displayed mathematical equations we define a breakable variant in
+% \cref{sec:breakable-display}.
+%
+% \Cref{sec:setspace-frontend} introduces the \packagename{setspace} front-end.
+%
+% In the last part, \cref{sec:smooth-ragged}, we introduce a novel way of generating ragged
+% paragraphs, which still is experimental.
+%
+%
+% \subsection{Prerequisites}\label{sec:packageprerequisites}
+%
+% Package \packagename{typog} requires \eTeX; it relies on the \LaTeXIII{}~interface. Parts of
+% it are based on package~\packagename{microtype}. However, if the respective functionality is
+% not used, \packagename{typog} can be used without \packagename{microtype}. The same holds
+% true for the \packagename{setspace} front-end.
+%
+% The package was tested with \programname{pdfTeX}~3.141592653-2.6-1.40.24 from the
+% TeX~Live distribution of~2022 as shipped by
+% \href{https://packages.debian.org/search?keywords=texlive}{Debian}.
+%
+%
+% \sectionfinish
+% \clearpage
+% \section{Package Options}\label{sec:package-options}
+%
+% Package \packagename{typog} does not override any existing macros or environments when
+% loaded, unless explicitly told by a package option.
+%
+% \begin{synopsis}
+% \begin{tabbing}
+% |\usepackage[|\,\dots|]{microtype}|
+% \=\texttt{\%\space}\textit{Only required for macros and} \\
+% \>\texttt{\%\space}\textit{environments in \cref{sec:microtype-frontend}.} \\
+% \\[-.5em]
+% |\usepackage[|\,\dots|]{setspace}|
+% \=\texttt{\%\space}\textit{Only required for macros in \cref{sec:setspace-frontend}.} \\
+% \\[-.5em]
+% |\usepackage[|\meta{OPTION}\dots|]{typog}|
+% \end{tabbing}
+% \end{synopsis}
+%
+% \index{package options|(}
+% The package \meta{OPTIONs} serve as configuration \meta{key}s, too. This means they can be
+% set with \hyperref[syn:typogsetup]{\code{typogsetup}} and their values can be retrieved with
+% \hyperref[syn:typogget]{\cs{typogget}}. Options that rely on package~\packagename{microtype}
+% are indicated with \doublequotes{\microtyperequiredmarker}.
+%
+% \begin{typogsetup}{}
+% \newcommand*{\indexpackageoption}[1]
+% {\index{package option>#1=\code{#1}}\index{#1=\code{#1}~(option)}\ignorespaces}
+% \begin{description}
+% [before={\let\oldmakelabel=\makelabel
+% \renewcommand{\makelabel}[1]
+% {\oldmakelabel{\termparbox{##1}}\phantomsection}},
+% font=\normalfont,
+% style=nextline,
+% vtietop]
+% \item[|breakpenalty=|\meta{penalty}]\label{item:breakpenalty}
+% \indexpackageoption{penalty}
+% \shiftedmarginnote{This sub-section is typeset with all \packagename{typog}~parameters
+% reset to their defaults by wrapping it in a
+% \hyperref[syn:typogsetup]{\code{typogsetup}}~environment with an empty argument.}
+% Penalty for a line break at various points. Default
+% value:~\the\typogget{breakpenalty}; initialized by the current
+% \cs{exhyphenpenalty}:~\the\exhyphenpenalty.
+%
+% \item[|debug|, |nodebug|]\label{item:debug}
+% \indexpackageoption{debug}
+% \indexpackageoption{nodebug}
+% Write package-specific debug information to the log file. Opposite: |nodebug|. The
+% default is not to log debug information.
+%
+% \item[|ligaturekern=|\meta{dim}]\label{item:ligaturekern}
+% \indexpackageoption{ligaturekern}
+% Set \meta{dim} of the kern that is inserted to split a ligature in
+% macro\hyperref[syn:nolig]{\cs{nolig}}. See
+% \cref{sec:break-ligatures}.\shiftedmarginnote{We access the configuration values with
+% \hyperref[syn:typogget]{\cs{typogget}}.} Default
+% value:~\milliem{\typogget{ligaturekern}}.
+%
+% \item[|mathitalicscorrection=|\meta{dim}]\label{item:mathitalicscorrection}
+% \indexpackageoption{mathitalicscorrection}
+% Italics correction in math mode. See \cref{sec:manual-italic-correction} and also the
+% complementary configuration
+% option~\hyperref[item:textitalicscorrection]{|textitalicscorrection|}. Default
+% value:~\the\typogget{mathitalicscorrection}.\footnote{Note that 1\,mu is
+% \nativetextfraction{1}{18}\,em of the mathematical font's~em.}
+%
+% \item[|raise*=|\meta{dim}]\label{item:raise}
+% \indexpackageoption{raise*}
+% Set the length by which selected characters (dash, hyphen, times, and number dash) are
+% raised. Default value:~0pt.
+%
+% Only the raise amounts for guillemets are unaffected by this option.
+%
+% \item[|raisecapitaldash=|\meta{dim}]\label{item:raisecapitaldash}
+% \indexpackageoption{raisecapitaldash}
+% Set the length that the \cs{textendash} is raised in
+% \hyperref[syn:capitaldash]{\cs{capitaldash}}. See \cref{sec:capital-dash}. Default
+% value:~\milliem{\the\typogget{raisecapitaldash}}.
+%
+% \item[|raisecapitalhyphen=|\meta{dim}]\label{item:raisecapitalhyphen}
+% \indexpackageoption{raisecapitalhyphen}
+% Set the length that the hyphen character~\sample{-} is raised in
+% \hyperref[syn:capitalhyphen]{\cs{capitalhyphen}}. See
+% \cref{sec:capital-hyphen}.\shiftedmarginnote{This description list is protected against
+% breaking items across pages within the first three lines by
+% \hyperref[syn:vtietop]{\code{vtietop}}.} Default
+% value:~\milliem{\the\typogget{raisecapitalhyphen}}.
+%
+% \item[|raisecapitaltimes=|\meta{dim}]\label{item:raisecapitaltimes}
+% \indexpackageoption{raisecapitaltimes}
+% Set the length that the multiplication symbol~\sample{\texttimes} is raised in
+% \hyperref[syn:capitaltimes]{\cs{capitaltimes}}. See \cref{sec:mult-sign}. Default
+% value:~\milliem{\the\typogget{raisecapitaltimes}}.
+%
+% \item[|raisecapitalguillemets=|\meta{dim}]\label{item:raisecapitalguillemets}
+% \indexpackageoption{raisecapitalguillemets}
+% Set the length that single and double guillemets are raised in the uppercase versions of
+% the guillemet macros. See \cref{sec:guillemets}. Default
+% value:~\milliem{\the\typogget{raisecapitalguillemets}}.
+%
+% \item[|raiseguillemets=|\meta{dim}]\label{item:raiseguillemets}
+% \indexpackageoption{raiseguillemets}
+% Set the length that single and double guillemets are raised in the lowercase versions of
+% the guillemet macros. See \cref{sec:guillemets}. Default
+% value:~\milliem{\the\typogget{raiseguillemets}}.
+%
+% \item[|raisefiguredash=|\meta{dim}]\label{item:raisefiguredash}
+% \indexpackageoption{raisefiguredash}
+% Set the length that the \cs{textendash} is raised in
+% \hyperref[syn:figuredash]{\cs{figuredash}}. See \cref{sec:number-dash}. Default
+% value:~\milliem{\the\typogget{raisefiguredash}}.
+%
+% \item[|shrinklimits=\{|\meta{limit-1}, \meta{limit-2}, \meta{limit-3}|\}|\quad\microtyperequiredmarker\label{item:shrinklimits} \\
+% |stretchlimits=\{|\meta{limit-1}, \meta{limit-2}, \meta{limit-3}|\}|\quad\microtyperequiredmarker]\label{item:stretchlimits}
+% \indexpackageoption{shrinklimits}
+% \indexpackageoption{stretchlimits}
+% Set the three limits, given in \nativetextfraction{1}{1000}\,em, of shrinkability and
+% stretchability for the respective levels. They are used in
+% \hyperref[syn:setfontshrink]{\code{setfontshrink}} (|shrinklimits| triple only),
+% \hyperref[syn:setfontstretch]{\code{setfontstretch}} (|stretchlimits| triple only), and
+% \hyperref[syn:setfontexpand]{\code{setfontexpand}} (both triples of limits). See
+% \cref{sec:font-expansion-control}.
+%
+% New \meta{limit-\#} values replace old ones. If one or more limits of the triple should
+% remain unchanged pass a \smash{\sample{*}} instead of a number.
+%
+% \makeatletter
+% Defaults for |shrinklimits| are \mbox{\typog@default@shrink@i, \typog@default@shrink@ii,
+% \typog@default@shrink@iii} and those for |stretchlimits| are
+% \mbox{\typog@default@stretch@i, \typog@default@stretch@ii, \typog@default@stretch@iii}.
+% \makeatother
+%
+% Both options can be used when loading the package and in the document preamble, but
+% \emph{not} in the document body.
+%
+% \item[|slashkern=|\meta{dim}]\label{item:slashkern}
+% \indexpackageoption{slashkern}
+% Set the size of the kerns before and after \hyperref[syn:kernedslash]{\cs{kernedslash}}.
+% See \cref{sec:slash-with-kern}. Default value:~\milliem{\typogget{slashkern}}.
+%
+% \item[|textitalicscorrection=|\meta{dim}]\label{item:textitalicscorrection}
+% \indexpackageoption{textitalicscorrection}
+% Italics correction fallback-value; used if \cs{fontdimen1} is zero. See
+% \cref{sec:manual-italic-correction} on manual italic correction and also the
+% complementary configuration
+% option~\hyperref[item:mathitalicscorrection]{|mathitalicscorrection|}. Default
+% value:~\milliem{\typogget{textitalicscorrection}}.
+%
+% \item[|trackingttspacing=|\code{\{\meta{outer-spacing}\}}\quad\microtyperequiredmarker]\label{item:trackingttspacing}
+% \indexpackageoption{trackingttspacing}
+% Set the outer spacing of all typewriter fonts if used in environment~\code{settracking}
+% as described in \cref{sec:tracking-control}.
+%
+% The argument \meta{outer-spacing} gets passed to \packagename{microtype}'s
+% \cs{SetTracking} option~\code{outer spacing}~\cite[Sec.~5.3]{package:microtype}. If it
+% contains commas, enclose the whole argument in curly braces. Default argument
+% value:~\mbox{\typogget{trackingttspacing}}.
+%
+% The option can be used when loading the package and in the document preamble, but
+% \emph{not} in the document body.
+%
+% By default this option is unset.
+% \end{description}
+% \end{typogsetup}
+% \index{package options|)}
+%
+%
+% \sectionfinish
+% \clearpage
+% \section{Macros and Environments}\label{sec:macros-and-envs}
+%
+% \begin{whittyquote}
+% Easy things should be easy, and \\
+% hard things should be possible. \\
+% \capitalemdash*~\propername{Larry Wall}
+% \end{whittyquote}
+%
+% \noindent
+% This is the \doublequotes{User Manual}~section of the documentation, where we describe all
+% user-relevant macros and environments that are defined in package~\packagename{typog}.
+%
+% We follow the naming convention that every environment whose name ends with \code{\dots par}
+% issues a \cs{par} at its end. Environments with different name suffixes never close
+% with~\cs{par}.
+%
+% \bigskip
+%
+% \noindent
+% \DescribeEnv{typogsetup}
+% Configure\index{configuration}\index{setup} the package with the given \meta{keys}. An empty
+% argument of \code{typogsetup} resets all \meta{keys} to their default values.
+%
+% \begin{synopsis}\label{syn:typogsetup}
+% \cs{begin}|{typogsetup}|\marg{keys}
+% \dots{}
+% \cs{end}|{typogsetup}|
+% \end{synopsis}
+%
+% The package can be (re-)configured\index{reconfigure} at any point with
+% \cs{typogsetup}\marg{keys}, or --~for localized changes~-- as
+%
+% \begin{codeexample}
+% 12\=\kill
+% \cs{begin}|{typogsetup}|\marg{keys} \\
+% \> \dots \\
+% \cs{end}|{typogsetup}|
+% \end{codeexample}
+%
+% \noindent
+% where \meta{keys} have the same format as the package options described in
+% \cref{sec:package-options}.
+%
+% \begin{usecases}
+% \cs{typogsetup} can substitute configuring the package at load-time or serve as an
+% addition.~\visualpar Using the |typogsetup|~environment allows to fine-tune the parameters
+% for a specific use, e.\,g., display-sized text.~\visualpar It even is conceivable that a
+% well-established \packagename{typog}-configuration gets attached to font-changing macros
+% like \cs{rm}, \cs{sf},~etc.
+% \end{usecases}
+%
+%
+% \noindent
+% \DescribeMacro{\typogget}
+% Sometimes the user needs to access internal configuration values of
+% package~\packagename{typog}. This can be done in a safe way without resorting to code that
+% is bracketed by \cs{makeatletter}/\cs{makeatother} with the help of the following macro.
+%
+% \begin{synopsis}\label{syn:typogget}
+% \cs{typogget}\marg{key}
+% \end{synopsis}
+%
+% Retrieve the configuration value that is associated with~\meta{key}. For a list of available
+% \meta{key}s see~\cref{sec:package-options}.
+%
+% \begin{usecase}
+% Raise glyphs by the same amount as configured with \packagename{typog}.
+%
+% \begin{codeexample}
+% 12\=\kill
+% \cs{newcommand*}\{\cs{seesubst}\} \\
+% \> \{\cs{raisebox}\= \{\cs{typogget}\{raisecapitalguillemets\}\}\% \\
+% \> \> \{\cs{rightarrowhead}\}\} \\
+% \cs{renewcommand*}\{\cs{labelitemi}\} \\
+% \> \{\cs{raisebox}\= \{\cs{typogget}\{raisecapitaldash\}\}\{\cs{cdot}\}\}
+% \end{codeexample}
+%
+% The latter only is useful inside of an \code{itemize}~environment of course.
+% \end{usecase}
+%
+%
+% \subsection{Information}\label{sec:information}\index{information}
+%
+% \begin{whittyquote}
+% Never forget: The visual output counts; \\
+% it must always be checked, [\dots]. \\
+% \marginnote{The em-dash at then end of the quote is height-adjusted with
+% \hyperref[syn:capitalemdash]{\cs{capitalemdash*}}.}%
+% \capitalemdash*~\propername{Udo Wermuth}~\cite{wermuth:2017a}
+% \end{whittyquote}
+%
+% \noindent
+% We define some functions for introspection of the typesetting process.
+%
+%
+% \subsubsection{Font Information}\label{sec:font-information}
+% \index{font>information}
+%
+% \DescribeMacro{\fontsizeinfo}
+% Capture the font~size\footnote{We use \cs{fontdimen6}, the em-height as the font
+% size.}\index{font>size} and line~spacing\footnote{The line~spacing simply is
+% \cs{baselineskip}.}\index{line spacing} at the point where \cs{fontsizeinfo} \emph{is called}
+% in macro~\meta{cs-name}. Both dimensions are measured in points~(pt) and the results are
+% rounded to tenths.
+%
+% \begin{synopsis}\label{syn:fontsizeinfo}
+% \cs{fontsizeinfo}\marg{cs-name}
+% \end{synopsis}
+%
+% The call to \cs{fontsizeinfo} introduces a pair of macros to access the stored values. The
+% unstarred version~\cs{cs-name} expands to the lengths including their units (i.\,e.,~pt), the
+% starred version~\cs{cs-name*} omits the units. The separating slash is
+% \hyperref[syn:kernedslash]{\cs{kernedslash}}, which is introduced in
+% \cref{sec:slash-with-kern}.
+%
+% \begin{note}
+% The \cs{baselineskip} can contain a rubber (stretch/shrink) component, however,
+% \cs{fontsizeinfo} will not display these parts.
+% \end{note}
+%
+% \begin{usecases}
+% Colophon.~\visualpar Font test pages.
+% \end{usecases}
+%
+%
+% \subsubsection{Paragraph- and Page-Breaking Trace}\label{sec:paragraph-and-pagebraking-trace}
+%
+% \DescribeEnv{typoginspect}
+% \DescribeEnv{typoginspectpar}
+% The environments |typoginspect| and |typoginspectpar| turn on the tracing of paragraphs and
+% pages; optionally they display the parbox' contents. These environments can assist the user
+% in identifying typographic problems in a quantitative way without getting distracted by
+% unrelated information in the trace or the \filesystem{log}-file.
+%
+% \begin{synopsis}\label{syn:typoginspect}
+% \cs{begin}|{typoginspect}|\oarg{option}\marg{id}
+% \dots{}
+% \cs{end}|{typoginspect}| \\[\smallskipamount]
+% \cs{begin}|{typoginspectpar}|\oarg{option}\marg{id} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{typoginspectpar}|
+% \end{synopsis}
+%
+% The \meta{id} is an arbitrary string that identifies the results in the
+% \filesystem{log}-file. If the mandatory argument is empty, \packagename{typog} constructs a
+% unique value.
+%
+%
+% \paragraph{Option}
+%
+% \begin{description}[style=nextline]
+% \item[|tracingboxes|{[}=\meta{size}{]}]
+% Specify the maximum box breadth and box depth reported in the log. If \meta{size} is
+% omitted the maximum values are assumed; this is similar to the \cs{tracingboxes}
+% macro~\cite[p.~312]{abrahams:2020}.
+% \end{description}
+%
+% \begin{caution}
+% The end-of-trace marker sometimes gets placed too early and the trace seems truncated.
+% \LaTeX{} reliably logs the requested the trace information, but the write operations for
+% trace data and \cs{immediate}\cs{write} which is used to print the end-tag are not
+% synchronized.
+% \end{caution}
+%
+%
+% \paragraph{\LaTeX{} \filesystem{log}-file and trace.}
+% The trace data in the \filesystem{log}-file is bracketed by \acronym{XML}-tags.
+%
+% \begin{widecodeexample}
+% <typog-inspect\textvisiblespace
+% id="\meta{id}"\textvisiblespace
+% job="\meta{jobname}"\textvisiblespace
+% line="\meta{line-number}"\textvisiblespace
+% page="\meta{page-number}"> \\
+% ~~\dots \\
+% </typog-inspect>
+% \end{widecodeexample}
+%
+% \noindent
+% where the \meta{id} is the user-supplied, unique\footnote{It has turned out advantageous to
+% use unique \meta{id}s. However, \meta{id}s are \emph{not required} to be distinct.}
+% identifier of the group, \meta{jobname} is the value of \cs{jobname}, \meta{line-number}
+% records the \cs{inputlineno} of the \cs{begin}~of the group, and \meta{page-number} gets
+% replaced with the current value of the page counter.
+%
+% \begin{itemize}[noindent]
+% \item Any text tool can be used to ferret out the tags. \propername{Emacs} users will find
+% \mbox{\code{(occur \meta{regexp})}} to be useful.
+%
+% \item As long as the tags are not nested \programname{sed} or \programname{perl}
+% extract the information gathered by~|typoginspect|, for example:
+%
+% \begin{codeexample}
+% sed \= -ne '/<typog-inspect\textvisiblespace id="\dots"/,\textbackslash\#</typog-inspect>\#p' \\
+% \> < jobname.log
+% \end{codeexample}
+%
+% or
+%
+% \begin{codeexample}
+% perl \= -ne '\= \$a=0 if /<\textbackslash/typog-inspect>/; \textbackslash \\
+% \>\> print \$\_ if \$a; \textbackslash \\
+% \>\> \$a=1 if /<typog-inspect\textvisiblespace id="\dots"/' \textbackslash \\
+% \> < jobname.log
+% \end{codeexample}
+%
+% \item The companion program~\programname{typog-grep} is tailored to extract the information
+% marked up by |typoginspect| and~|typoginspectpar| even if the environments are nested.
+%
+% We reproduce the complete manual page of \programname{typog-grep} in \Cref{app:typog-grep}.
+% \end{itemize}
+%
+% \begin{tips}
+% \begin{itemize}[nestedinspecialsection, notopsep]
+% \item It may be necessary to run whatever \LaTeX~engine with a larger log-file line length,
+% to prevent wrapped lines. With short lines the wannabe \acronym{XML} opening tags can
+% get wrapped and thus become unrecognizable to dumb postprocessors. To avoid wrapped
+% lines prepend
+%
+% \begin{codeexample}
+% /usr/bin/env max\_print\_line=2147483647
+% \end{codeexample}
+%
+% to the command-line. The value~\(2147483647 = 2^{31} - 1\) effectively disables all line
+% wrapping by \LaTeX.
+%
+% As both \command{pdflatex} and \command{lualatex} support changing their configuration on
+% a by-call basis with option~\code{-cnf-line=\meta{STRING}} an alternative to the above
+% example is to add
+%
+% \begin{codeexample}
+% -cnf-line=max\_print\_line=2147483647
+% \end{codeexample}
+%
+% to the respective command-line.
+%
+% \item If more trace information is needed just add \cs{tracing\dots} calls right after
+% \code{\string\begin\{typoginspect\}}
+% or~\code{\string\begin\{typoginspectpar\}}.\specialsectionendhere
+% \end{itemize}
+% \end{tips}
+%
+%
+% \phantomsection
+% \paragraph{Investigating the badness of a paragraph.}\label{sec:investigating-paragraph-badness}\index{paragraph>badness}
+%
+% It is generally unnecessary to determine the \emph{exact} classification of a paragraph's
+% badness~\cite[p.~97n]{knuth:1986}, though the curious user can switch on logging of
+% \TeX's~line-break information with
+% \cs{tracingparagraphs}|=1|\footnote{Reference~\citenum{wermuth:2016} provides an
+% exceptionally detailed discussion of the output of \cs{tracingparagraphs}.} or simply use
+% the \hyperref[syn:typoginspect]{typoginspect}~environment and check the suffixes
+%
+% \begingroup
+% \centering
+% |@@|\meta{breakpoint-number} |line| \meta{line-number}|.|\meta{suffix}
+% \par
+% \endgroup
+%
+% \noindent
+% of each line in the paragraph, where for \meta{suffix} the following mapping
+% holds~\cite[p.~99]{knuth:1986}:
+% \begin{equation*}
+% 0 \mapsto \text{very loose},\quad
+% 1 \mapsto \text{loose},\quad
+% 2 \mapsto \text{decent, and}\quad
+% 3 \mapsto \text{tight}.
+% \end{equation*}
+%
+% \begin{example}
+% \let\oldsample=\sample
+% \renewcommand*{\sample}[1]{\oldsample{\texttt{#1}}}
+% \par\medskip
+% \noindent
+% |@@17: line 15.1- t=142289 s=93.58414 a=2.86073 -> @@16|
+%
+% \begin{enumerate}[noitemsep]
+% \item The feasible breakpoint~\sample{@@} number~17 in the paragraph leads to
+% \item \sample{line}~15, which is the loose~\sample{.1} last~\sample{-} line of the
+% paragraph.
+% \item Up to this breakpoint the paragraph has picked up total demerits~\sample{t}
+% of~142289.
+% \item The following two values only show up if\/ \(\cs{lastlinefit} \not= 0\):
+% \begin{enumerate}[beginpenalty=10000, nosep]
+% \item The shortfall~\sample{s} and
+% \item glue~\sample{a} or~\sample{g}.\footnote{The author is unaware of any descriptions
+% of \code{s}, \code{a}, or~\code{g}. The interested reader is referred to the source
+% code, e.\,g., \filesystem{pdftex.web}; search for \code{print("\textvisiblespace s=")}.
+% In the weaved documentation the first relevant section is~\S1851.}
+% \end{enumerate}
+% \item The best\footnote{\singlequotes{Best} means the minimum-demerits path in the graph of
+% the feasible breakpoints, which has been constructed for the paragraph.} way to get
+% here, i.\,e., |@@17| is via~\sample{->} breakpoint~\sample{@@}~16.\specialsectionendhere
+% \end{enumerate}
+% \end{example}
+%
+% \begin{note}
+% When package~\packagename{microtype}'s font expansion feature jumps in the reports on
+% \doublequotes{Loose \textbackslash hbox (badness \dots)} and \doublequotes{Tight
+% \textbackslash hbox (badness \dots)} \shiftedmarginnote{All of our guillemets were raised
+% by \milliem{\the\typogget{raiseguillemets}}.} contain the amount of shrinking or expansion
+% as parenthesized values (units are thousandths of the current font's~em) like, e.\,g.,
+%
+% \begin{codeexample}
+% \textbackslash T1/erewhon-LF/m/n/9/@/@ (-13) \dots
+% \end{codeexample}
+%
+% or
+%
+% \begin{codeexample}
+% \textbackslash T1/erewhon-LF/m/n/9/@/@/10ls (+7) \dots
+% \end{codeexample}
+%
+% An \sample{ls} appended to the font name specification indicates that
+% \packagename{microtype}'s letter~spacing feature is active and changed the tracking by that
+% many thousands on an em as indicated before~\sample{ls}.
+% \end{note}
+%
+%
+% \paragraph{Investigating page-breaks.}\index{page break}
+%
+% Use \code{\cs{tracingpages}=1} or the \hyperref[syn:typoginspect]{typoginspect}~environment
+% to switch on tracing of \TeX's page-break
+% information~\cite[p.~112n]{knuth:1986}.\footnote{See also the discussion of the \TeX~output
+% routines by \propername{Solomon}~\cite{solomon:1990}.}
+%
+% The first time vertical material enters a new page, \TeX{} logs
+%
+% \begingroup\tt
+% \centering
+% \%\% goal height=\meta{text-height}, max depth=\meta{max-depth} \\
+% \par
+% \endgroup
+%
+% \noindent
+% where \meta{text-height} is the total height \TeX{} wants to achieve and~\meta{max-depth} is
+% the maximum depth of the hbox in the last line of the page is allowed to have without
+% considering \meta{text-height} to be exceeded. For example:
+%
+% \begingroup\tt
+% \centering
+% \%\% goal height=598.0, max depth=5.0 \\
+% \par
+% \endgroup
+%
+% For every vertical breakpoint \TeX{} records
+%
+% \begingroup\tt
+% \centering
+% \% t=\meta{total-height} g=\meta{goal-height} b=\meta{badness} p=\meta{penalty} c=\meta{cost}
+% \par
+% \endgroup
+%
+% Here, \meta{total-height} and \meta{goal-height} are the current total height of the page and
+% the current goal height to achieve with respect to this vertical breakpoint.
+%
+% The value of \meta{penalty} and \meta{cost} can be infinite, which would be indicated with an
+% asterisk~\sample{\texttt{*}} instead of a numerical value. The best vertical breakpoint
+% found so far on the current page is indicated by a trailing sharp-sign~\sample{\texttt{\#}}.
+%
+% \begin{example}
+% \let\oldsample=\sample
+% \renewcommand*{\sample}[1]{\oldsample{\texttt{#1}}}
+% \begin{widecodeexample}
+% \% t=351.3 plus 11.0 minus 1.0 g=553.9 b=10000 p=-300 c=100000\#
+% \end{widecodeexample}
+%
+% \begin{enumerate}[noitemsep, notopsep]
+% \item At this vertical breakpoint the total page height~\sample{t} is 351.3\,pt. We have
+% picked up glue with 11\,pt~stretchability and~1\,pt~shrinkability along the way.
+%
+% \item The current goal height~\sample{g} is 553.9\,pt. If the initial goal height was
+% 598\,pt we can deduce that some space for other vertical material was subtracted.
+%
+% \item The badness~\sample{b} of this vertical break is horrendous which is expected for the
+% first lines on a page since breaks so early are rightfully considered infinitely bad.
+%
+% \item The penalty~\sample{p} at this point actually is a bonus.
+%
+% \item As the badness is 10000 the cost for a break is calculated
+% to~100000.\specialsectionendhere
+% \end{enumerate}
+% \end{example}
+%
+%
+% \subsection{Hyphenation}\label{sec:latex-hyphenation}
+% \index{hyphenation}
+%
+% \TeX's and thus \LaTeX's hyphenation algorithm is highly sophisticated, yet the document
+% author sometimes lacks convenient macros to solve seemingly trivial typographic tasks. For
+% example, to hyphenate a compound~word connected by a hyphen.
+%
+% \DescribeMacro{\allowhyphenation}
+% \TeX{} inhibits breaks of the component words by default. The following macro rectifies the
+% problem.
+%
+% \begin{synopsis}
+% \cs{allowhyphenation}
+% \end{synopsis}
+%
+% Macro~\cs{allowhyphenation}\index{hyphenation>re-enable automatic} re-enables automatic
+% hyphenation after \TeX{} has turned it off, for example, in the innocuous case of a
+% hyphenated compound.
+%
+% The admittedly simple rules when \TeX{} auto-hyphenates and when not give rise to so many
+% different, yet interesting cases that we devote \cref{tab:hyphens-and-hyphenations} to them.
+% \begingroup
+% \let\textfrac=\nativetextfraction
+% The seemingly special cases shown there are not that uncommon, e.\,g., consider
+% \singlequotes{\mbox{spin-\textfrac{1}{2}}} which is coded as |\mbox{spin-\textfrac{1}{2}}|.
+% A line break between the text and the fraction would garble the term.
+% \endgroup
+%
+% \begin{usecases}
+% All examples from the bottom of \cref{tab:hyphens-and-hyphenations} on
+% \cpageref{tab:hyphens-and-hyphenations}.~\visualpar
+%
+% Fix line breaks of index-entries in a narrow index:
+%
+% \begin{codeexample}
+% Halbgruppe, Transformations\cs{allowhyphenation}\cs{mbox}\{-\}\cs{,}-\nolig*-\nolig*-
+% \end{codeexample}
+%
+% \noindent
+% The first part, \singlequotes{Transformations} is allowed to be hyphenated, but a break
+% after the hyphen is prohibited as it results in a prowling em-dash at the beginning of the
+% next line.~\visualpar
+%
+% Re-enable hyphenation when a macro decays into a \cs{hbox}:
+%
+% \begin{codeexample}
+% Einselement\cs{allowhyphenation}\cs{rlap}\{,\}\cs{footnote}\{\dots\}
+% \end{codeexample}
+%
+% where \cs{rlap} is equivalent to something like
+% \code{\cs{makebox}[0pt]\{\#1\cs{hss}\}}.~\visualpar
+%
+% Use \cs{allowhyphenation} to turn on hyphenation of the first word of a paragraph as,
+% e.\,g., in a narrow index or a \cs{marginpar}:
+%
+% \begin{codeexample}
+% \cs{marginpar}\{\cs{allowhyphenation} Kontakttransformationen\}
+% \end{codeexample}
+%
+% \noindent
+% A common trick to sweet-talk \TeX{} into hyphenating the first word of a paragraph is to
+% put \cs{hskip0pt} in front of it.
+% \end{usecases}
+%
+% \begin{table}\small
+% \centering
+% \caption[Hyphens and automatic hyphenation]
+% {\TeX{} offers plenty of possibilities to hyphenate a compound.~\visualpar We use
+% the sample \singlequotes{hyphenated-compound} to show various code examples and
+% the results that they produce. The parts are automatically hyphenated like this:
+% \singlequotes{hyphenated}~\(\rightarrow\) \singlequotes{hy-phen-ated} and
+% \singlequotes{compound}~\(\rightarrow\) \singlequotes{com-pound}.}
+% \label{tab:hyphens-and-hyphenations}
+%
+% \begin{nofontexpansion}
+% \newcommand*{\zbox}[1]
+% {\hfuzz=\maxdimen
+% \overfullrule=0pt
+% \raisebox{\normalbaselineskip}{\parbox[t]{0pt}{\hspace{0pt}#1}}}
+%
+% \sbox{\listlabelbox}{hyphenated-compound}
+% \begin{tabularx}{\linewidth}{@{}p{12em}l>{\fussy\RaggedRight}X@{}}
+% \toprule
+% \LaTeX-Code & \makebox[\wd\listlabelbox][l]{Result} & Note \\
+% \midrule
+% \code{hyphenated-compound} &
+% \zbox{hyphenated-compound} &
+% Most frequently used code; the hyphen~\sample{\code{-}} expands to
+% \code{\cs{discretionary}\mbox{\{-\}\{\}\{-\}}} rendering the parts un-breakable \\
+%
+% \code{hyphenated\cs{mbox}\{-\}\%}\newline
+% \code{compound} &
+% \zbox{hyphenated\mbox{-}compound} &
+% Suppress hyphenation with the \cs{mbox} in the compound \\
+%
+% \code{\cs{mbox}\{hyphenated-\%}\newline
+% \code{compound\}} &
+% \zbox{\mbox{hyphenated-compound}} &
+% Avoid line break and thus hyphenation \\
+%
+% \midrule
+%
+% \code{hyphenated\cs{hyp}}\newline
+% \code{compound} &
+% \zbox{hyphenated\hyp compound} &
+% Macro~\cs{hyp} defined in package
+% \packagename{hyphenat}~\cite{package:hyphenat} \\
+%
+% \addlinespace
+% \midrule
+%
+% \code{hyphenated\%}\newline
+% \cs{allowhyphenation}\code{-\%}\newline
+% \code{compound} &
+% \zbox{hyphenated\allowhyphenation-compound} &
+% Macro~\cs{allowhyphenation} of package~\packagename{typog}; only unblock
+% hyphenation of the first part \\
+%
+% \code{hyphenated-\%}\newline
+% \cs{allowhyphenation}\newline
+% \code{compound} &
+% \zbox{hyphenated-\allowhyphenation compound} &
+% Macro~\cs{allowhyphenation} of package~\packagename{typog}; only unblock
+% hyphenation of the second part \\
+%
+% \code{hyphenated\%}\newline
+% \cs{allowhyphenation}\newline
+% \cs{mbox}\code{\{-\}\%}\newline
+% \code{compound} &
+% \zbox{hyphenated\allowhyphenation\mbox{-}compound} &
+% Macro~\cs{allowhyphenation} of package~\packagename{typog}; hyphenate first
+% part and keep the original hyphen unbreakable \\
+%
+% \code{hyphenated\%}\newline
+% \cs{allowhyphenation}\code{-\%}\newline
+% \cs{allowhyphenation}\newline
+% \code{compound} &
+% \zbox{hyphenated\allowhyphenation-\allowhyphenation compound} &
+% Macro~\cs{allowhyphenation} of package~\packagename{typog}; hyphenate both
+% parts, similar to \cs{hyp} shown above \\
+%
+% \addlinespace
+% \bottomrule
+% \end{tabularx}
+% \end{nofontexpansion}
+% \end{table}
+%
+% \noindent
+% Whenever using \cs{-}, the short-hand form of \cs{discretionary\{-\}\{\}\{\}}, authors
+% writing in a foreign language should reconsider whether it really beats \cs{hyphenation} or
+% \cs{babelhyphenation}\footnote{\cs{babelhyphenation} is the multi-lingual extension of \TeX's
+% \cs{hyphenation} and it is defined in package~\packagename{babel}~\cite{package:babel}}. in
+% the particular situation. However, sometimes \cs{-} actually \emph{is} the way to go.
+%
+% Let us assume we mark up proper names with
+%
+% \begin{codeexample}
+% \cs{DeclareRobustCommand}*\= \{\cs{propername}\}[1] \\
+% \> \{\cs{mbox}\{\cs{textsc}\{\#1\}\}\}
+% \end{codeexample}
+%
+% \noindent
+% and we want to have hyphenatable \foreignphrase{\doublequotes{\propername{Abel}sche Gruppe}}
+% or \foreignphrase{\doublequotes{\propername{Euklid}ischer Vektorraum}} without dropping the
+% markup. To that end we define commands that insert a hyphenation point at the right place:
+%
+% \begin{codeexample}
+% \cs{newcommand*}\= \{\cs{abelsche}\} \\
+% \> \{\cs{propername}\{Abel\}\cs{-}sche\} \\
+% \cs{newcommand*}\> \{\cs{euklidischer}\} \\
+% \> \{\cs{propername}\{Euklid\}i\cs{-}scher\}
+% \end{codeexample}
+%
+% \noindent
+% which are impossible to encode with \cs{hyphenation} or~\cs{babelhyphenation} as these expect
+% only letters and dashes as their arguments with spaces separating the words.
+%
+% \begin{tip}[Typewriter Fonts]
+% Sometimes it is desired to get a hyphenatable typewriter font. \LaTeX{} suppresses any
+% hyphenation for fonts in \cs{ttfamily} by un-defining their \cs{hyphenchar}s. If these are
+% reassigned, the usual hyphenation occurs again.
+%
+% So, a fictitious macro `\cs{code}' to typeset short pieces of code could look like this:
+%
+% \begin{codeexample}
+% \cs{newcommand*}\= \{\cs{code}\}[1] \\
+% \> \{\{\= \cs{ttfamily} \\
+% \> \> \cs{hyphenchar}\cs{font}=`\cs{-}\cs{relax} \#1\}\}\specialsectionendhere
+% \end{codeexample}
+% \end{tip}
+%
+% \DescribeMacro{\breakpoint}
+% \DescribeMacro{\breakpoint*}
+% The empty discretionary construct~\cite[p.~95]{knuth:1986}, \cs{discretionary\{\}\{\}\{\}},
+% is so helpful that it deserves its own macro --~with a descriptive name.
+%
+% \begin{synopsis}
+% \cs{breakpoint} \\
+% \cs{breakpoint*}
+% \end{synopsis}
+%
+% The starred form inserts an empty discretionary,\index{hyphenation>empty discretionary} which
+% disables automatic hyphenation. The unstarred form inserts an empty discretionary and
+% immediately re-enables automatic hyphenation.
+%
+% The difference between \cs{breakpoint} and the \LaTeX{} macro~\cs{allowbreak} is not only
+% that the former has a starred form, but the penalty associated with \cs{breakpoint} is the
+% current\footnote{At this point in the document
+% \code{\string\exhyphenpenalty=\the\exhyphenpenalty} holds.} \cs{exhyphenpenalty}, whereas
+% \cs{allowbreak} statically assigns a zero~penalty.
+%
+% \begin{usecase}
+% Prefixes that end in a hyphen inside of a pair of parenthesis:
+%
+% \begin{codeexample}
+% \cs{mbox}\{(pre-)\}\cs{breakpoint*} \cs{propername}\{Hilbert\} space\specialsectionendhere
+% \end{codeexample}
+% \end{usecase}
+%
+% \DescribeEnv{hyphenmin}
+% \sinceversion{Since v0.3}
+% Set the values of \cs{lefthyphenmin} and \cs{righthyphenmin} confined to an environment.
+%
+% \begin{synopsis}\label{syn:hyphenmin}
+% \cs{begin}|{hyphenmin}|\oarg{left-hyphen-minimum}\marg{hyphen-minimum} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{hyphenmin}|
+% \end{synopsis}
+%
+% Without optional argument |hyphenmin| sets both \cs{lefthyphenmin} and \cs{righthyphenmin} to
+% \meta{hyphen-minimum}. When called with an optional argument it sets \cs{lefthyphenmin} to
+% \meta{left-hyphen-minimum} and \cs{righthyphenmin} to \meta{hyphen-minimum}.\footnote{The
+% current values for \cs{lefthyphenmin} and \cs{righthyphenmin} in this document
+% are~\the\lefthyphenmin{} and~\the\righthyphenmin, respectively.}
+%
+% \begin{usecase}
+% If the hyphen minimums were \emph{increased} e.\,g.~in the preamble: Reduce the hyphen
+% minimum in the index or other multi-column environments with narrow lines to regain
+% hyphenation possibilities.~\visualpar Use a large \meta{hyphen-minimum} to disable
+% hyphenation.
+% \end{usecase}
+%
+%
+% \subsection{Disable\kernedslash Break Ligatures}\label{sec:break-ligatures}
+% \index{ligature}
+%
+% \DescribeMacro{\nolig*}
+% Break a ligature without introducing a hyphenation opportunity.
+%
+% \begin{synopsis}\label{syn:nolig-star}
+% \cs{nolig*}\oarg{kerning}
+% \end{synopsis}
+%
+% Inserting \cs{nolig*} disables a ligature at the given point by a kern. Set the size of the
+% kern\index{kerning>ligature} with \hyperref[item:ligaturekern]{|ligaturekern|} or override
+% this value with \meta{kerning} as thousandths of the current font's~em.
+%
+% \begin{usecases}
+% \cs{nolig*} can be useful in headings, where additional hyphenation points are
+% unwelcome.~\visualpar In fonts with an overly rich set of ligatures \cs{nolig*} offers a
+% straightforward means to suppress unwanted ligatures at non-hyphenatable
+% positions.~\visualpar Rectify the appearance of a pseudo ligature, i.\,e., two adjacent
+% characters that look like a ligature, but actually are not.
+% \end{usecases}
+%
+% \noindent
+% \DescribeMacro{\nolig}
+% Break a ligature and introduce a hyphenation opportunity.
+%
+% \begin{synopsis}\label{syn:nolig}
+% \cs{nolig}\oarg{kerning}
+% \end{synopsis}
+%
+% Inserting \cs{nolig} disables a ligature at the given point as \cs{nolig*} does \emph{and}
+% introduces a hyphenation opportunity with
+% penalty~\hyperref[item:breakpenalty]{|breakpenalty|}.
+%
+% \begin{important}[\packagename{hyperref} bookmarks]\index{hyperref=\packagename{hyperref} (package)}
+% If a \cs{nolig} --~whether starred or un-starred~-- occurs in an argument that is processed
+% with package~\packagename{hyperref} for inclusion into the document's
+% \acronym{PDF}-bookmarks\index{PDF=\acronym{PDF}}\index{bookmark} an additional argument is
+% necessary to parse the macro. This argument either is \cs{relax} or~the empty
+% group~(\code{\{\}}).
+%
+% \begin{synopsis}
+% \begin{tabbing}
+% \cs{nolig*}\oarg{kerning}\cs{relax}\qquad\= \cs{nolig}\oarg{kerning}\cs{relax} \\
+% \cs{nolig*}\oarg{kerning}\code{\{\}}\> \cs{nolig}\oarg{kerning}\code{\{\}}
+% \end{tabbing}
+% \end{synopsis}
+%
+% The prototypical places where this processing-for-\acronym{PDF}-bookmarks happens are the
+% sectioning macros, e.\,g., \cs{chapter}, \cs{section}, \cs{subsection},~etc.
+%
+% \LaTeX{} will bail out with an error if the extra argument is not passed to \cs{nolig} in
+% these situations.
+%
+% Alternatively use \cs{texorpdfstring}~\cite[Sec.~4.1.2, p.~22]{package:hyperref}.
+% \end{important}
+%
+% \begin{usecases}
+% \cs{nolig} can be used with just about any ligature that needs to be split into its
+% parts.~\visualpar It also has proven beneficial in separating pairs of characters that are
+% kerned to tightly (e.\,g.~the \sample{ij}, as in bi\itcorr{2}jection, which is particularly
+% distractive here, for it occurs at the boundary of two syllables).
+% \end{usecases}
+%
+%
+% \subsection{Manual Italic Correction}\label{sec:manual-italic-correction}\label{italic correction}
+%
+% \DescribeMacro{\itcorr}
+% \DescribeMacro{\itcorr*}
+% The italic correction offered by \TeX{} or \LaTeX{} sometimes needs a helping hand.
+%
+% \begin{synopsis}\label{syn:itcorr}
+% \cs{itcorr}\marg{strength} \\
+% \cs{itcorr*}\marg{strength}
+% \end{synopsis}
+%
+% In text mode macro~\cs{itcorr} inserts a kern whose width is proportional to \cs{fontdim1},
+% which is the font's italic correction. If \cs{fontdim1} happens to be zero (e.\,g.~for an
+% upright font), \cs{itcorr} uses the value set with
+% \hyperref[item:textitalicscorrection]{\code{textitalicscorrection}} instead of \cs{fontdim1}.
+% The starred version always uses
+% \hyperref[item:textitalicscorrection]{\code{textitalicscorrection}}. In math mode
+% macro~\cs{itcorr} uses the value set with
+% \hyperref[item:mathitalicscorrection]{\code{mathitalicscorrection}}\footnote{Separate
+% adjustments may be desirable if the math font's italics have markedly different slants.} in
+% both the starred and the unstarred form.
+%
+% Typical slant angles of serif italics fonts range from 8\textdegree{} to~18\textdegree{} and
+% thus values for |textitalicscorrection| from .14 to~.32. Note: \meta{strength} can be
+% negative and fractional \meta{strength}s are allowed.
+%
+% \begin{usecases}
+% Stronger or weaker correction than |\/|.~\visualpar Correct a non-slanted or non-italicized
+% font.~\visualpar Negative correction at the left-hand side\footnote{Groff has the machinery
+% for left-italic-correction. Its font-metrics files support per glyph
+% left-italic-correction values and users can access them conveniently via~\sample*{\cs{,}}.}
+% of italics, i.\,e., compensate \doublequotes{shift-to-the-right effect} of
+% italics.~\visualpar Positive correction at the left-hand side of italics, e.\,g., an
+% opening parenthesis or square bracket followed by an
+% italic~\sample{\itshape\itcorr{8}f\itcorr{7}} (before:~8, after:~7) or
+% \sample{\itshape\itcorr{4}y\itcorr{1}} (before:~4, after:~1) reaching far to the left below
+% the baseline.
+% \end{usecases}
+%
+%
+% \paragraph{The \meta{strength} parameter explained.}
+%
+% \TeX{} records the slant angle~\(\alpha\) of a font in \cs{fontdim1} as \(\mbox{1\,pt} \times
+% \sin\alpha\). Rephrased the formula means: \emph{How much horizontal space is required for a
+% letter slanted with ~\(\alpha\) that is 1\,pt high?} So, \cs{itcorr}\marg{strength}
+% calculates
+% \begin{displaymath}
+% \meta{strength} \times \mbox{1\,pt} \times \sin\alpha.
+% \end{displaymath}
+%
+% A well-chosen \meta{strength} should be the absolute minimum value which avoids that the
+% glyphs typeset in italics collide with other --~usually non-italics~-- letters or symbols
+% unless this disturbs the consistency of the overall tracking.
+%
+% Correction of the right-hand side and \mbox{\(\alpha > 0\)}: A reasonable first guess of
+% \meta{strength} is the highest point where the rightmost part of the letter would touch a
+% rule angled at \(\alpha\) with respect to the baseline. The correction of the left-hand side
+% and \mbox{\(\alpha > 0\)} considers the lowest \singlequotes{touching} point below the
+% baseline on the left-hand side of the letter. Negative values of \(\alpha\) exchange the
+% reference points.
+%
+% \iffalse
+%<*slantangle>
+prologues := 3;
+truecorners := 1;
+linecap := butt;
+
+input TEX;
+TEXPRE("%&latex" & char(10) & "\documentclass{article}\begin{document}");
+TEXPOST("\end{document}");
+
+string roman_font;
+roman_font := "pplr8r"; % URW Palladio L - Roman
+
+string italics_font;
+italics_font := "pplri8r"; % URW Palladio L - Italic
+
+u := 360;
+
+font_scale := 10;
+
+pair loc[];
+loc[1] := .2[origin, (u, 0)];
+loc[2] := .5[origin, (u, 0)];
+loc[3] := .8[origin, (u, 0)];
+
+picture letter_H;
+letter_H := thelabel.top("H" infont italics_font scaled font_scale, loc[1]);
+
+picture letter_L;
+letter_L := thelabel.top("L" infont italics_font scaled font_scale, loc[2]);
+
+picture letter_a;
+letter_a := thelabel.top("a" infont italics_font scaled font_scale, loc[3]);
+
+path slant_angle;
+slant_angle := lrcorner letter_H + (14, 0) -- lrcorner letter_H + (-6, 0) -- urcorner letter_H + (3.5, 0);
+
+pair base_point;
+base_point := (xpart point 2 of slant_angle, ypart point 0 of slant_angle) ;
+
+pair angle_label;
+angle_label := point 2 of slant_angle + (0, -12);
+
+
+beginfig(1);
+ draw letter_H;
+ draw slant_angle;
+ draw point 2 of slant_angle -- base_point dashed evenly;
+ draw point 1 of slant_angle -- base_point withpen pencircle scaled 2pt;
+
+ label.rt(TEX("$\alpha$"), angle_label);
+
+ draw letter_L;
+ draw slant_angle shifted (xpart lrcorner letter_L - xpart lrcorner letter_H + 2, 0);
+
+ draw letter_a;
+ draw slant_angle shifted (xpart lrcorner letter_a - xpart lrcorner letter_H - 3, 0);
+endfig;
+end
+%</slantangle>
+% \fi
+%
+% \Cref{fig:slant-angle} shows how \meta{strength} and \(\alpha\) are related. Moreover, it
+% demonstrates how intricate italics correction is.
+%
+% \begin{figure}
+% \centering
+% \includegraphics{slant-angle-1.mps}
+% \caption[Some letters of an italics font.]
+% {Some letters of an italics font. We use the capital~\sample{H} to measure the
+% angle~\(\alpha\) between the plumb-line (drawn dashed) and a tangent to the
+% rightmost parts of the glyph. The length of the plumb-line is proportional to
+% \meta{strength} and the short, thick part of the baseline symbolizes the resulting
+% italics correction.~\visualpar The middle example, the capital~\sample{L}, shares
+% \(\alpha\) with \sample{H} but obviously needs a far smaller \meta{strength} or
+% even no correction at all.~\visualpar The \sample{a} at the right-hand side is an
+% example of why \TeX{} allows to assign an italic~correction to each individual
+% character of a font. Not only features the lowercase~\sample{a} a
+% larger~\(\alpha\) --~despite being a member of the same font~-- but its serif adds
+% as much to the width as the slanted stem.\label{fig:slant-angle}}
+% \vspace{-3\baselineskip}
+% \llap{\parbox{\marginparwidth}
+% {\marginnoteformat
+% We center the last lines of each figure and table caption with the help of
+% \hyperref[syn:lastlinecenteredpar]{\code{lastlinecenteredpar}}.}
+% \hspace*{\marginparsep}}
+% \end{figure}
+%
+%
+% \subsection{Apply Extra Kerning}\label{sec:extra-kerning}
+% \index{kerning>extra}
+%
+% Package \packagename{typog} supplies two sets of macros to kern some of the punctuation
+% symbols. One is for forward slashes the other, more extensive one, for hyphens.
+%
+%
+% \subsubsection{Slash}\label{sec:slash-with-kern}
+% \index{kerning>forward slash}
+%
+% \DescribeMacro{\kernedslash}
+% \DescribeMacro{\kernedslash*}
+% Macro~\cs{kernedslash} expands to a forward slash~(\sample{\itcorr{3}\char`/}) with some
+% extra space around it.
+%
+% \begin{synopsis}\label{syn:kernedslash}
+% \cs{kernedslash} \\
+% \cs{kernedslash*}
+% \end{synopsis}
+%
+% The starred form is unbreakable, the non-starred version introduces a break point with
+% penalty~\hyperref[item:breakpenalty]{|breakpenalty|} after the slash. Configure the kerning
+% around the slash with~\hyperref[item:slashkern]{|slashkern|}.
+%
+% If the word following the slash should not be hyphenated append \cs{nobreak} after
+% \cs{kernedslash*}.
+%
+% \begin{usecases}
+% \cs{kernedslash} improves the appearance of pairs of years typeset in lining numerals:
+% \meta{year\textsubscript{1}}/\meta{year\textsubscript{2}}.~\visualpar The macro has proven
+% helpful in many cases where the right hand side of the slash starts with a capital as, for
+% example, \meta{city}/\meta{state-code} (\acronym{US}-specific) or
+% \meta{anything}/\meta{noun} (any language that capitalizes \meta{noun}).
+% \end{usecases}
+%
+%
+% \subsubsection{Hyphen}\label{sec:hyphen-with-kern}
+% \index{kerning>hyphen}
+%
+% \DescribeMacro{\kernedhyphen}
+% \DescribeMacro{\kernedhyphen*}
+% Macros \cs{kernedhyphen*} and \cs{kernedhyphen} expand to a hyphen~(\sample{-}) with given
+% kerning to its left and to its right.
+%
+% \begin{synopsis}\label{syn:kernedhyphen}
+% \cs{kernedhyphen}\oarg{raise}\marg{left-kerning}\marg{right-kerning} \\
+% \cs{kernedhyphen*}\oarg{raise}\marg{left-kerning}\marg{right-kerning}
+% \end{synopsis}
+%
+% Typeset an unbreakable hyphen with \cs{kernedhyphen*} or a breakable hyphen (like \cs{hyp} of
+% package \packagename{hyphenat}~\cite{package:hyphenat}) with \cs{kernedhyphen} and apply some
+% kerning to left and to the right of it. The values \meta{left-kerning} and
+% \meta{right-kerning} are multiplied with one thousandth of the current font's~em to get the
+% size of the kern.
+%
+% The optional argument~\meta{raise}, also given in \nativetextfraction{1}{1000}\,em, allows to
+% adjust the height of the hyphen similar to the macros described in
+% \cref{sec:raise-characters}. In text mode the special argument~\sample{|*|} for \meta{raise}
+% transfers the current value of \hyperref[item:raisecapitalhyphen]{\code{raisecapitalhyphen}}.
+% The default for \meta{raise} is zero.
+%
+% \DescribeMacro{\leftkernedhyphen}
+% \DescribeMacro{\leftkernedhyphen*}
+% \DescribeMacro{\rightkernedhyphen}
+% \DescribeMacro{\rightkernedhyphen*}
+% We also define specialized versions for kerning on the left-hand side or the right-hand side
+% only. These macros work like their two-argument counterparts and set the appropriate other
+% kerning to zero.
+%
+% \begin{synopsis}\label{syn:leftkernedhyphen}\label{syn:rightkernedhyphen}
+% \cs{leftkernedhyphen}\oarg{raise}\marg{left-kerning} \\
+% \cs{leftkernedhyphen*}\oarg{raise}\marg{left-kerning} \\
+% \cs{rightkernedhyphen}\oarg{raise}\marg{right-kerning} \\
+% \cs{rightkernedhyphen*}\oarg{raise}\marg{right-kerning}
+% \end{synopsis}
+%
+% \begin{usecases}
+% Composites in the form \meta{math}-\meta{noun} in languages where nouns are
+% capitalized.~\visualpar Composites where one or both sides of the hyphen are typeset in
+% different fonts, like, \meta{small-caps}-\meta{roman}.
+% \end{usecases}
+%
+%
+% \subsection{Raise Selected Characters}\label{sec:raise-characters}
+% \index{raised character}
+%
+% Usually all hyphens and dashes of a font are designed to join lowercase letters. This holds
+% also true for most of our \cs{labelitem}\meta{N} markers, bullets, stars, and even fancy
+% dingbats. If these hyphens and dashes connect uppercase letters (or lining numerals) they
+% sometimes appear to low; they disrespect the glyphs' symmetry axis. A similar situation
+% arises if |itemize|~list markers precede an uppercase letter, a lining numeral, or a big
+% mathematical operator.
+%
+% We introduce a set of macros for the most common cases that allow typsetting these characters
+% at a user definable, adjusted height above the baseline. Users can base their own
+% definitions of raised characters on their associated dimensions.\footnote{Also compare with
+% Ex.~12 in Ref.~\citenum{wermuth:2023} for an attempt to automate vertical alignment.}
+%
+% \begin{caution}
+% The height adjustment disables a font's built-in kerning.
+% \end{caution}
+%
+% \noindent
+% General note for all raised hyphen-like macros: Prefer the starred version if applied in
+% front of any punctuation.
+%
+%
+% \subsubsection{Capital Hyphen}\label{sec:capital-hyphen}
+% \index{raised character>hyphen}
+%
+% \DescribeMacro{\capitalhyphen}
+% \DescribeMacro{\capitalhyphen*}
+% In many fonts the height of the hyphen character~\sample{-} above the baseline is optimized
+% for lowercase letters. In languages that capitalize their nouns as, e.\,g., German, this may
+% be too low for compounds involving capitals.
+%
+% \begin{synopsis}\label{syn:capitalhyphen}
+% \cs{capitalhyphen} \\
+% \cs{capitalhyphen*}
+% \end{synopsis}
+%
+% The unstarred version introduces a hyphenation opportunity right after the hyphen character
+% (with penalty~\hyperref[item:breakpenalty]{|breakpenalty|}) whereas the starred version does
+% not. The actual amount the hyphen gets raised in \cs{capitalhyphen} is determined by
+% \hyperref[item:raisecapitalhyphen]{|raisecapitalhyphen|}.
+%
+% \begin{usecases}
+% In languages that capitalize their nouns, the typical use-case is between an
+% \meta{ab\-bre\-vi\-a\-tion} and a \meta{noun} when \meta{ab\-bre\-vi\-a\-tion} is a string
+% of uppercase letters. The same holds true for a connection of an uppercase variable in
+% mathematical mode and a \meta{noun} starting with a capital letter.~\visualpar Abbreviated
+% compound first names (e.\,g., A.\capitalhyphen* M.~Legendre) can be joined with the starred
+% version.~\visualpar Also, the starred form is suited for \acronym{ISO~8601}-formatted dates
+% if they are composed with lining-style numerals.
+% \end{usecases}
+%
+%
+% \subsubsection{Capital Dash}\label{sec:capital-dash}
+% \index{raised character>en-dash}
+%
+% \DescribeMacro{\capitalendash}
+% \DescribeMacro{\capitalendash*}
+% \DescribeMacro{\capitaldash}
+% \DescribeMacro{\capitaldash*}
+% The situation of the en-dash~\sample{--} is almost identical to the one of the hyphen
+% character~\sample{-} described in the previous section or the number dash to be introduced in
+% the next section.
+%
+% \begin{synopsis}\label{syn:capitalendash}\label{syn:capitaldash}
+% \begin{tabbing}
+% \cs{capitalendash}\qquad\= \cs{capitaldash} (alias) \\
+% \cs{capitalendash*} \> \cs{capitaldash*} (alias)
+% \end{tabbing}
+% \end{synopsis}
+%
+% The unstarred version introduces a hyphenation opportunity right after the dash (with
+% penalty~\hyperref[item:breakpenalty]{|breakpenalty|}) whereas the starred version does not.
+% The actual amount the hyphen gets raised in \cs{capitaldash} is determined by
+% \hyperref[item:raisecapitalhyphen]{|raisecapitaldash|}.
+%
+% \begin{usecases}
+% Letter ranges as used in the title of an index.~\visualpar Any mixed letter-digit ranges
+% (of capital letters and lining-style numerals) as in e.\,g., Sec.~B\capitaldash* 2.
+% \end{usecases}
+%
+% \noindent
+% \DescribeMacro{\capitalemdash}
+% \DescribeMacro{\capitalemdash*}
+% For completeness we also introduce a raised em-dash~\sample{---}. It behaves just like its
+% en-dash sibling.
+%
+% \begin{synopsis}\label{syn:capitalemdash}
+% \cs{capitalemdash} \\
+% \cs{capitalemdash*}
+% \end{synopsis}
+%
+% \begin{usecases}
+% Item symbols in \code{itemized} lists if the item text starts with an uppercase
+% letter.~\visualpar Theorem headings, like, e.\,g., \mbox{Definition 6.2 \capitalemdash{}
+% \textsc{Lie} Algebra}.
+% \end{usecases}
+%
+%
+% \subsubsection{Number Dash (Figure Dash)}\label{sec:number-dash}
+% \index{raised character>number dash}
+%
+% \DescribeMacro{\figuredash}
+% \DescribeMacro{\figuredash*}
+% The en-dash often gets used as separator for numerical ranges. In most fonts it has the
+% correct height above baseline for oldstyle numerals,
+% e.\,g.~\oldstylenums{12}--\oldstylenums{34}--\oldstylenums{56}--\oldstylenums{78}, but with
+% lining numerals --~depending on the font~-- it may look like it suffers from
+% \doublequotes{broken suspenders}:
+% 12\textendash34\textendash56\textendash78.\marginnote{\cs{figuredash} yields
+% 12\figuredash34\figuredash56\figuredash78 for sans-serif and {\rm
+% 12\figuredash34\figuredash56\figuredash78} for the roman typeface.} The situation is similar
+% to \cs{capitaldash} and \cs{capitalhyphen} discussed in
+% \cref{sec:capital-hyphen,sec:capital-dash}.
+%
+% \begin{synopsis}\label{syn:figuredash}
+% \cs{figuredash} \\
+% \cs{figuredash*}
+% \end{synopsis}
+%
+% The unstarred version introduces a hyphenation opportunity right after the en-dash with
+% penalty~\hyperref[item:breakpenalty]{|breakpenalty|} whereas the starred version does not.
+% The actual amount the en-dash gets raised in \cs{figuredash} is determined by
+% \hyperref[item:raisefiguredash]{|raisefiguredash|}.
+%
+% Values of .05em to .1em are typical for fonts that need this kind of correction and~.1em is a
+% good starting point. \Cref{tab:raisefiguredash} summarizes some findings.
+%
+% \begin{table}
+% \centering
+% \caption[Suggested raise amounts for \cs{figuredash}]%
+% {Suggested values for raising the en-dash between lining numerals of some selected
+% fonts.}
+% \label{tab:raisefiguredash}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}l>{\RaggedRight}p{20em}@{}}
+% \toprule
+% Raise & Font Name \\
+% em & \\
+% \midrule
+% 0 & Alegreya\index{font>Alegreya}, Arvo\index{font>Arvo},
+% Bitter\index{font>Bitter}, Clara\index{font>Clara},
+% \acronym{EB}~Garamond\index{font>EB Garamond=\acronym{EB} Garamond},
+% Gentium\index{font>Gentium},
+% Ibarra Real Nova\index{font>Ibarra Real Nova},
+% \acronym{Inria}~Serif\index{font>Inria Serif=\acronym{Inria} Serif},
+% Libertine\index{font>Libertine}, Libertinus\index{font>Libertinus},
+% Merriweather\index{font>Merriweather},
+% \acronym{PT}~Serif\index{font>PT Serif=\acronym{PT} Serif},
+% Roboto Slab\index{font>Roboto Slab}, Spectral\index{font>Spectral},
+% \acronym{STIX}\index{font>STIX=\acronym{STIX}}, and many more \\
+% .05 & fbb\index{font>fbb}, Source Serif Pro\index{font>Source Serif Pro} \\
+% .0667 & Libre Baskerville\index{font>Libre Baskerville},
+% Crimson Pro\index{font>Crimson Pro},
+% Erewhon\index{font>Erewhon}, Droid Serif\index{font>Droid Serif} \\
+% .1 & \acronym{GFS}~Artemisia\index{font>GFS Artemisia=\acronym{GFS} Artemisia},
+% Libre Caslon\index{font>Libre Caslon},
+% Coelacanth\index{font>Coelacanth}, Crimson Pro\index{font>Crimson Pro},
+% Crimson Text\index{font>Crimson Text},
+% \TeX{} Gyre~Pagella\index{font>TeX Gyre Pagella=\TeX{} Gyre Pagella},
+% Quattrocento\index{font>},
+% \acronym{TX}~Fonts\index{font>TX Fonts=\acronym{TX} Fonts},
+% \acronym{ADF}~Venturis\index{font>ADF Venturis=\acronym{ADF} Venturis},
+% and many more \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{table}
+%
+% Other macros may be redefined with \cs{figuredash} for a consistent appearance of the copy,
+% like, for example, \cs{citedash} (package~\packagename{cite}~\cite{package:cite}), or
+% \cs{crefrangeconjunction} (package~\packagename{cleveref}~\cite{package:cleveref}).
+%
+% \begin{usecase}
+% The key customers of \cs{figuredash} are the |PAGES|~entries of bibliography
+% databases.~\visualpar In an index generated with \command{makeindex} the range
+% delimiter~\code{delim\_r} is a candidate for \cs{figuredash*}.
+% \end{usecase}
+%
+%
+% \subsubsection[Multiplication Sign]%
+% {Multiplication Sign -- Times~\sample{\texttimes}}\label{sec:mult-sign}
+% \index{raised character>multiplication sign}
+%
+% \DescribeMacro{\capitaltimes}
+% The \cs{capitaltimes}~macro is a variation of the
+% \hyperref[syn:capitalhyphen]{\cs{capitalhyphen}}~theme.
+%
+% \begin{synopsis}\label{syn:capitaltimes}
+% \cs{capitaltimes}
+% \end{synopsis}
+%
+% In text mode it expands to an appropriately raised \cs{texttimes}, and in math~mode to a
+% raised \cs{times} binary~operator, where
+% \hyperref[item:raisecapitaltimes]{|raisecapitaltimes|} determines the amount of
+% upward-shifting applied; it never inserts any break points.
+%
+% \begin{usecase}
+% Prime use are two- or higher-dimensional shape specifications with lining numerals or
+% uppercase letters in mathematical mode as, for example, matrix or tensor sizes.
+% \end{usecase}
+%
+%
+% \subsubsection{Guillemets}\label{sec:guillemets}
+% \index{raised character>guillemets}
+%
+% Another possible typographic problem this package addresses is that both sets --~single and
+% double quotes~-- of guillemets may suffer from a too small distance to the baseline.
+%
+% For the implementation \packagename{typog} relies on the T1\footnote{Font
+% encoding~T1\index{font>encoding} can be forced via \cs{usepackage}|[T1]\{fontenc\}| in the
+% document preamble.}~font encoding not on package~\packagename{babel}.
+%
+%
+% \paragraph{Lowercase Versions.}
+% \DescribeMacro{\singleguillemetleft}
+% \DescribeMacro{\singleguillemetright}
+% \DescribeMacro{\doubleguillemetleft}
+% \DescribeMacro{\doubleguillemetright}
+% \begin{synopsis}\label{syn:singleguillemetleft}\label{syn:doubleguillemetleft}
+% \begin{tabbing}
+% \cs{singleguillemetleft}\qquad\= \cs{singleguillemetright} \\
+% \cs{doubleguillemetleft}\> \cs{doubleguillemetright}
+% \end{tabbing}
+% \end{synopsis}
+%
+% \noindent
+% For consistency and easy accessibility we define height-adjusted left and right single
+% guillemets as \cs{singleguillemetleft} and \cs{singleguillemetright}; double guillemets are
+% available with \cs{doubleguillemetleft} and \cs{doubleguillemetright}. Their heights above
+% the baseline are collectively adjusted with
+% \hyperref[item:raiseguillemets]{|raiseguillemets|}.
+%
+%
+% \paragraph{Uppercase Versions.}
+%
+% \DescribeMacro{\Singleguillemetleft}
+% \DescribeMacro{\Singleguillemetright}
+% \DescribeMacro{\Doubleguillemetleft}
+% \DescribeMacro{\Doubleguillemetright}
+% \begin{synopsis}\label{syn:Singleguillemetleft}\label{syn:Doubleguillemetleft}
+% \begin{tabbing}
+% \cs{Singleguillemetleft}\qquad\= \cs{Singleguillemetright} \\
+% \cs{Doubleguillemetleft}\> \cs{Doubleguillemetright}
+% \end{tabbing}
+% \end{synopsis}
+%
+% \noindent
+% The companion set of single, double, left, and right quotes corrected for uppercase letters
+% or lining numerals is \cs{Singleguillemetleft} and \cs{Singleguillemetright} and
+% \cs{Doubleguillemetleft} and \cs{doubleguillemetright}. Mnemonic: These macros start with an
+% uppercase letter. Their height above the baseline is adjusted with
+% \hyperref[item:raisecapitalguillemets]{|raisecapitalguillemets|}. Values of .025em to .075em
+% are typical for fonts that need this kind of correction. \Cref{tab:raiseguillemets}
+% summarizes some findings.
+%
+% \begin{table}
+% \centering
+% \caption[Suggested raise amounts for guillemets]%
+% {Suggested values for raising guillemets of some selected fonts.}
+% \label{tab:raiseguillemets}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}cc>{\RaggedRight}p{20em}@{}}
+% \toprule
+% \multicolumn{2}{@{}c}{Raise} & Font Name \\
+% Lowercase & Uppercase & \\
+% em & em & \\
+% \midrule
+% 0 & .05\hphantom{00} &
+% \acronym{EB}~Garamond\index{font>EB Garamond=\acronym{EB} Garamond},
+% Libertinus\index{font>Libertinus},
+% Merriweather\index{font>Merriweather}, and many more \\
+% .025 & .05\hphantom{00} & Gentium\index{font>Gentium} \\
+% .04\hphantom{0} & .0667 &
+% \acronym{ADF}~Baskervald\index{font>ADF Baskervald=\acronym{ADF} Baskervald} \\
+% .05\hphantom{0} & .0625 &
+% \acronym{GFS}~Artemisia\index{font>GFS Artemisia=\acronym{GFS} Artemisia},
+% \acronym{GFS}~Didot\index{font>GFS Didot=\acronym{GFS} Didot} \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{table}
+%
+% \begin{tip}
+% Define shorthand macros that simplify the application of guillemets, like, e.\,g.,
+%
+% \begin{codeexample}
+% \cs{newcommand*}\= \{\= \cs{singlequotes}\}[1] \\
+% \> \{\cs{singleguillemetright} \#1\% \\
+% \> \> \cs{singleguillemetleft}\} \\
+% \cs{let}\cs{sq}=\cs{singlequotes}
+% \end{codeexample}
+%
+% and similar definitions for \cs{Singlequotes}, \cs{doublequotes}, and~\cs{Doublequotes}.
+%
+% Users working according to the French typesetting conventions will want to add extra
+% spacing between the guillemets and the macro argument already in these macros.
+% \end{tip}
+%
+% \noindent
+% Whether the guillemets must be height-adjusted for lowercase letters depends on the font.
+% Careful judgment at various magnifications with a variety of samples is necessary.
+%
+%
+% \paragraph{Interaction with package~\packagename{csquotes}.}
+% \index{csquotes=\packagename{csquotes} (package)}
+%
+% The users of package~\packagename{csquotes}
+% can hook up the guillemets as defined by \packagename{typog}
+% with \cs{DeclareQuoteStyle}:
+%
+% \begin{codeexample}
+% 12\=\kill
+% \cs{DeclareQuoteStyle}\{typog-guillemets\} \\
+% \> \{\cs{doubleguillemetright}\}\%\qquad\= opening outer mark \\
+% \> \{\cs{doubleguillemetleft}\}\% \> closing outer mark \\
+% \> \{\cs{singleguillemetright}\}\% \> opening inner mark \\
+% \> \{\cs{singleguillemetleft}\}\% \> closing inner mark
+% \end{codeexample}
+%
+% \noindent
+% As always, the influence of package~\packagename{babel} on \packagename{csquotes} has to be
+% put into consideration. See Sec.~8 of the \packagename{csquotes}~manual for a description of
+% its configuration possibilities.
+%
+% \begin{usecase}
+% All-capital words as for example acronyms put in guillemets that are raised somewhat almost
+% always look better, whether using the French typographic convention (guillemets pointing
+% outward plus some extra kerning) or the other way round (guillemets pointing inward).
+% \end{usecase}
+%
+% \begin{futuredirection}
+% A correction in the other direction, i.\,e., lowering certain characters may also be
+% desirable, to visually align them to the surrounding copy. Parentheses and in particular
+% square brackets around all-lowercase text come into mind.
+% \end{futuredirection}
+%
+%
+% \subsection[Align Last Line]
+% {Align Last Line of a Paragraph}\label{sec:align-last-line}
+% \index{paragraph>align last line}
+%
+% The usual algorithms of \LaTeX{} typeset the last line of a paragraph flush with the left
+% margin unless |center|, |raggedleft| or |Centering|, |FlushRight|
+% (package~\packagename{ragged2e}~\cite{package:ragged2e}) are in effect. For an instructive
+% discussion consult Ch.~17, \doublequotes{Paragraph End}, of Ref.~\citenum{eijkhout:2007}.
+% The following environments allow to adjust the last lines of paragraphs in different ways.
+%
+% \DescribeEnv{lastlineraggedleftpar}
+% \DescribeEnv{lastlineflushrightpar}
+% The environment |lastlineraggedleftpar|\index{paragraph>align last line>flush right} adjusts
+% the various skips such that the last lines of the paragraphs gets typeset flush with the
+% right margin.
+%
+% \begin{synopsis}\label{syn:lastlineraggedleftpar}\label{syn:lastlineflushrightpar}
+% \cs{begin}|{lastlineraggedleftpar}| \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{lastlineraggedleftpar}| \\[\smallskipamount]
+% |lastlineflushrightpar|~(alias)
+% \end{synopsis}
+%
+% The name |lastlineflushrightpar| is an alias for~\code{lastlineraggedleftpar}.
+%
+% \DescribeEnv{lastlinecenteredpar}
+% Center\index{paragraph>align last line>centered} the last lines of the paragraphs enclosed by
+% this environment.\footnote{Also compare the approach taken in Ref.~\citenum{wermuth:2018}.}
+%
+% \begin{synopsis}\label{syn:lastlinecenteredpar}
+% \cs{begin}|{lastlinecenteredpar}| \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{lastlinecenteredpar}|
+% \end{synopsis}
+%
+% \begin{usecases}
+% |lastlineflushrightpar|: Narrow, justified parts of the text put flush against the right
+% margin.~\visualpar |lastlinecenteredpar|: Table or figure captions typeset justified as
+% centered boxes.
+% \end{usecases}
+%
+%
+% \needtocspace
+% \subsection[Fill Last Line]
+% {Fill Last Line of a Paragraph}\label{sec:fill-last-line}
+% \index{paragraph>fill last line}
+%
+% The problem of when and how to \singlequotes{fill} the last line of a paragraph is quite
+% intricate. We first define the problem then we proceed to general purpose functions and we
+% close the section with specific environments to control the length of the last line.
+%
+%
+% \subsubsection{Problem Definition}
+%
+% Depending on the value of \cs{parindent}, either zero or nonzero, there may be the desire to
+% control the length of the last line of a paragraph.
+%
+% \iffalse
+%<*crookedparagraphs>
+prologues := 3;
+
+def draw_filled_rectangle(expr lower_left, upper_right, color) =
+ fill lower_left -- (xpart upper_right, ypart lower_left) --
+ upper_right -- (xpart lower_left, ypart upper_right) --
+ cycle
+ withcolor color;
+enddef;
+
+
+u := 100;
+
+em := 10;
+linelength := 2u;
+baselineskip := 1.2em;
+parskip := 3;
+parindent := 2.5em;
+
+cmykcolor line_color;
+line_color := (.08, 0, 0, .18); % cold silver
+
+color customred[];
+customred[1] := (.890, .282, .282);
+customred[2] := (.831, .110, .110);
+customred[3] := (.686, .043, .043);
+customred[4] := (.569, .000, .000);
+customred[5] := (.420, .000, .000);
+
+color margin_color;
+margin_color := customred[2];
+
+
+beginfig(1); % short line -- gap
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (1.1em, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((parindent, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip), margin_color);
+endfig;
+
+
+beginfig(2); % short line -- covered
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (2parindent, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((parindent, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip), margin_color);
+endfig;
+
+
+beginfig(3); % completely filled line -- no clear paragraph break
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip - parskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip - parskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip - parskip),
+ margin_color);
+endfig;
+
+
+beginfig(4); % completely filled line -- opened right margin
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - parindent, y + 1em), line_color);
+ y := y - baselineskip - parskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color);
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -3baselineskip - parskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -3baselineskip - parskip),
+ margin_color);
+endfig;
+end
+%</crookedparagraphs>
+% \fi
+%
+% \begin{enumerate}
+% \item\label{item:o1}
+% \(\cs{parindent} > 0\) \cite[O1]{wermuth:2018}
+%
+% \begin{minipage}{\linewidth}
+% If the last line of a paragraph is shorter than the \cs{parindent} of the following
+% paragraph a visual gap tears open.
+%
+% \begin{center}
+% \includegraphics{crooked-paragraphs-1.mps}
+% \end{center}
+% \end{minipage}
+%
+% The same problem arises with displayed math in a flush-left\footnote{The common practice of
+% centering displayed equations does not call for the manipulations of a paragraph's last
+% line discussed here.} setting, e.\,g., \packagename{amsmath}~\cite{package:amsmath} and
+% option~|fleqn|.\footnote{For displayed equations and \packagename{amsmath} the relevant
+% parameter is~\cs{mathindent}.}
+%
+% \begin{minipage}{\linewidth}
+% A possible remedy is to reflow the paragraph in a way that its last line is clearly wider
+% than \cs{parindent}; a typical suggestion being twice the~\cs{parindent}.
+%
+% \begin{center}
+% \includegraphics{crooked-paragraphs-2.mps}
+% \end{center}
+% \end{minipage}
+%
+% \item\label{item:o2}
+% \(\cs{parindent} = 0\) \cite[O2]{wermuth:2018}
+%
+% \begin{minipage}{\linewidth}
+% If the last line of a paragraph is completely filled with text, i.\,e., flush with the
+% right margin, it may become hard to spot the start of the following paragraph unless
+% \cs{parskip} is large.\footnotemark
+%
+% \begin{center}
+% \includegraphics{crooked-paragraphs-3.mps}
+% \end{center}
+% \end{minipage}\footnotetext{Package~\packagename{parskip} defines \cs{parskip}
+% as \mbox{6pt plus 2pt} for a base size of~10pt.}
+%
+% \medskip
+% \begin{minipage}{\linewidth}
+% A possible, more legible solution is to reformat the paragraph in a way such that its
+% last line leaves a marked gap with respect to the right margin.
+%
+% \begin{center}
+% \includegraphics{crooked-paragraphs-4.mps}
+% \end{center}
+% \end{minipage}
+%
+% The suggestions for the gap-width vary from two~em to twice the width of a
+% \singlequotes{typical} \cs{parindent}\footnote{% For example, \LaTeX's class
+% \packagename{article} uses a \cs{parindent} of~25pt.} for the gap~\cite{carlisle:1996}.
+% \end{enumerate}
+%
+% \begin{tip}
+% In theory both problems, O1 and O2 can be resolved by either shortening or prolonging the
+% last line of the paragraph. For the concrete case it is up to the user to decide which
+% direction to go and to choose the method that yields the most pleasing typographic results.
+%
+% \TeX{} always considers the paragraph in its entirety. Thus any change the user demands
+% \doublequotes{just for the last line} will permeate the whole paragraph and in unfortunate
+% cases botch it.
+%
+% Prudent users check the appearance of the problematic, original paragraph against one or
+% more corrected versions of it~-- at least visually. Quantitative comparisons can be
+% performed with the help of~\cs{tracingparagraphs}.
+% \end{tip}
+%
+% \begin{important}
+% For the techniques in the following two subsections to work the paragraphs treated with
+% them should have certain advantageous properties.
+%
+% \begin{itemize}
+% \item Technically, the paragraphs need to contain enough glue (see
+% e.\,g.~\cref{sec:sloppy-paragraphs}) to achieve a low badness such that the desired
+% paragraph end is deemed feasible by \TeX.
+%
+% \item Aesthetically, the paragraphs must be long enough to absorb the change in last-line
+% fill level otherwise their gray-values visibly deviate from the
+% average.\specialsectionendhere
+% \end{itemize}
+% \end{important}
+%
+%
+% \subsubsection{Manual Changes}\label{sec:fill-last-line-other-methods}
+%
+% Most \hyperref[item:o1]{O1} or \hyperref[item:o2]{O2} situations can be navigated with
+% do-it-yourself methods. Here are some common recipes.
+%
+% \begin{enumerate}
+% \item End-of-paragraph intervention.\label{enum:end-of-paragraph-intervention}
+%
+% \begin{enumerate}[notopsep]
+% \item Tie~\sample{\texttt{\char126}}\label{enum:tie-last-words}\index{paragraph>fill last line>tie}
+%
+% Tie the last words.
+%
+% The problem with the tie may be a hyphenation of one of the words that participates in
+% the tie. The next item avoids this disadvantage.
+%
+% \item \cs{mbox}\label{enum:mbox-last-words}\index{paragraph>fill last line>mbox=\cs{mbox}}
+%
+% Join the last words or inline equation at the end of the paragraph with an~\cs{mbox}.
+%
+% \item \cs{linebreak}\label{enum:linebreak}\index{paragraph>fill last line>linebreak=\cs{linebreak}}
+%
+% Add a \cs{linebreak} to the back part of the paragraph (approximately where the
+% \cs{mbox} of item~\ref{enum:mbox-last-words} would start) in a way that the last line
+% receives the desired length~\cite{wermuth:2022-8-2}. In turn the next-to-last lines
+% may become unsightly. Counteract this degradation e.\,g.~with
+% recipes~\ref{enum:vary-spacing} to~\ref{enum:vary-font-expansion}.
+% \end{enumerate}
+%
+% Tying and \cs{mbox}ing lend themselves to generalizations. We need not only tie at end of
+% a paragraph but fuse logical units of sentences or inline equations so that the relevant
+% information literally stays in the reader's focus. Cementing together text of course finds
+% an end when overfull lines start to show up.
+%
+% \item Uniform paragraph change.\label{enum:uniform-paragraph-change}
+%
+% \begin{enumerate}[notopsep]
+% \item Vary spacing.\label{enum:vary-spacing}\index{font>spacing}
+%
+% Modify the inter-word spacing, for example, with the macros introduced in
+% \cref{sec:looser-tighter-spacing}.
+%
+% Enclose the paragraph in either \hyperref[syn:loosespacing]{|loosespacing|}
+% or~\hyperref[syn:tightspacing]{|tightspacing|}.
+% Increase the spacing~\meta{level} until the last line gets the desired length.
+%
+% \item Vary font tracking.\label{enum:vary-font-tracking}\index{font>tracking}
+%
+% Enclose the paragraph in a \hyperref[syn:setfonttracking]{\code{setfonttracking}}~group.
+% See \cref{sec:tracking-control}. Increase or decrease the tracking in steps of
+% \nativetextfraction{1}{1000}\,em until the last line looks good.
+%
+% \item Vary font expansion.\label{enum:vary-font-expansion}\index{font>expansion}
+%
+% Enclose the paragraph in a \hyperref[syn:setfontexpand]{\code{setfontexpand}}~group. See
+% \cref{sec:font-expansion-control}.
+% \end{enumerate}
+%
+% \item A combination of any of the above items.
+%
+% \item Some curveballs.\label{enum:gonzo-tips}\par
+% \begin{enumerate}[notopsep]
+% \item If the paragraph already suffers from one of the problems that \TeX{} addresses with
+% \cs{doublehyphendemerits}, \cs{finalhyphendemerits}, or~\cs{adjdemerits}, crank up one or
+% all of these values to~10000 and observe whether the length of last line changes in the
+% desired direction.
+%
+% \item If any influential \packagename{microtype} features have been enabled try with one
+% more more of them \emph{disabled}. See, e.\,g.,
+% environment~\hyperref[syn:nofontexpansion]{\code{nofontexpansion}} in
+% \cref{sec:font-expansion-control}.
+% \end{enumerate}
+% \end{enumerate}
+%
+%
+% \subsubsection{Multi\capitalhyphen Purpose Environments}\label{sec:fill-last-line-gp-environments}
+%
+% \DescribeEnv{shortenpar}
+% \DescribeEnv{prolongpar}
+% The two environments |shortenpar|\index{paragraph>fill last
+% line>shortenpar=\code{shortenpar}} and |prolongpar|\index{paragraph>fill last
+% line>prolongpar=\code{prolongpar}} can be employed in quite general situations when a
+% paragraph should be typeset one line longer or shorter, e.\,g., to avoid a
+% widow~line\footnote{The last line of a paragraph becomes a \singlequotes{widow}\index{forlorn
+% line>widow} (ger.~\foreignphrase{Hurenkind}) if it starts the following page or column.} or
+% a club~line\footnote{The first line of a paragraph is called
+% \singlequotes{club}\index{forlorn line>club} or~\singlequotes{orphan}\index{forlorn
+% line>orphan} (ger.~\foreignphrase{Schusterjunge}) if it appears at the bottom of the page or
+% column.}~[\citenum{knuth:1986}, p.~104 and~\citenum{mittelbach:2018c}]. (See also
+% \cref{sec:vtie-paragraph} for special functions to avoid clubs or widows.)
+% \singlequotes{Accidentally}, they also change the length of the last line of the paragraph.
+%
+% \begin{synopsis}\label{syn:shortenpar}
+% \cs{begin}|{shortenpar}|
+% \dots{}
+% \cs{end}|{shortenpar}|
+% \end{synopsis}
+%
+% Environment |shortenpar| decreases the \cs{looseness} of the paragraph.\footnote{Command
+% \cs{looseness} is a \TeX{}~primitive~\cite[p.~103n]{knuth:1986}. A thorough discussion of
+% the interaction of \cs{linepenalty} and \cs{looseness} can be found in
+% Ref.~\citenum{wermuth:2017c}.} It performs well if the last line of the paragraph is short
+% or the whole paragraph is loose.
+%
+% \begin{synopsis}\label{syn:prolongpar}
+% \cs{begin}|{prolongpar}|
+% \dots{}
+% \cs{end}|{prolongpar}|
+% \end{synopsis}
+%
+% This environment increases the \cs{looseness} of the paragraph, which is why it works best
+% with decent or tight last lines that are almost full.
+%
+%
+% \subsubsection{Specialized Environments}\label{sec:fill-last-line-specialized-environments}
+%
+% We introduce environments not just skips to get the correct behavior --~set up all paragraph
+% parameters \emph{before} the paragraph ends~-- and, at the same time, limit the range of this
+% parameter change.
+%
+% \DescribeEnv{covernextindentpar}
+% Environment |covernextindentpar|\index{paragraph>fill last line>covernextindentpar=\code{covernextindentpar}}
+% can be helpful for \hyperref[item:o1]{case~O1}, i.\,e., a too short last line.
+%
+% \begin{synopsis}\label{syn:covernextindentpar}
+% \cs{begin}|{covernextindentpar}|\oarg{dim} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{covernextindentpar}|
+% \end{synopsis}
+%
+% The environment asks \TeX{} to extend the last line of a paragraph such that it takes at
+% least
+% \makeatletter\dumpmacro{\typog@covernextindentpar@nonzero@parindent}\makeatother{}
+% (if \(\cs{parindent} \not= 0\)),
+% \makeatletter\typog@covernextindentpar@zero@parindent\makeatother{}
+% (if \(\cs{parindent} = 0\)), or \meta{dim} if called with an optional argument.
+%
+% \DescribeEnv{openlastlinepar}
+% The next environment, |openlastlinepar|,\index{paragraph>fill last
+% line>openlastlinepar=\code{openlastlinepar}} takes care of \hyperref[item:o2]{case~O2},
+% i.\,e., a last line in a paragraph that is almost full or completely filled.
+%
+% \begin{synopsis}\label{syn:openlastlinepar}
+% \cs{begin}|{openlastlinepar}|\oarg{dim} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{openlastlinepar}|
+% \end{synopsis}
+%
+% It may resolve \hyperref[item:o2]{case~O2} as it attempts to prevent a completely filled line
+% by introducing a partly unshrinkable \cs{parfillskip}. Without optional argument the
+% threshold of unused last-line length is either
+% \makeatletter\dumpmacro{\typog@openlastlinepar@nonzero@parindent}\makeatother{} (if
+% \(\cs{parindent} \not= 0\)) or
+% \makeatletter\typog@openlastlinepar@zero@parindent\makeatother{} (if \(\cs{parindent} = 0\)).
+% The optional argument~\meta{dim} directly sets the gap threshold.
+%
+% Note that the application of this environment can be successful, this is, a completely filled
+% last line is avoided, but the result may be of \hyperref[item:o1]{type~O1} nonetheless.
+%
+%
+% \needtocspace
+% \Needspace{150pt}
+% \subsection{Spacing}\label{sec:spacing-control}\index{font>spacing}
+%
+% \begin{whittyquote}
+% 90~\% of design is typography. \\
+% And the other 90~\% is whitespace. \\
+% \capitalemdash*~\propername{Jeffrey Zeldman}
+% \end{whittyquote}
+%
+% \noindent
+% The functions described in this section rely only on plain \LaTeX. No extra packages are
+% required. Compare to the \packagename{microtype}-based functionality of
+% \cref{sec:microtype-frontend}.
+%
+%
+% \subsubsection[Looser\kernedslash Tighter]{Looser or Tighter Spacing}\label{sec:looser-tighter-spacing}\index{font>spacing>loose}\index{font>spacing>tight}
+%
+%
+% \begin{whittyquote}
+% Never try to adjust lines by squeezing or stretching the tracking. \\
+% Go for the subtle solution: adjust word spacing instead. \\
+% \capitalemdash*~\propername{Jan Middendorp}~\cite[p.~119]{middendorp:2014}
+% \end{whittyquote}
+%
+% \noindent
+% The environments in this section directly influence the spacing, this is, they change the
+% width and stretchability of the horizontal space.
+%
+% They at the one hand act gently by adjusting the spacing only by a small amount. On the
+% other hand they operate decidedly in controlling the glue associated with the adjusted space.
+% The latter also being important to ensure the monotonicity of the different \meta{level}s.
+% However, the strictly managed stretchability\slash shrinkability may lead to many overfull
+% boxes with \cs{fussy} or when applied to short lines.
+%
+% \DescribeEnv{loosespacing}
+% \DescribeEnv{tightspacing}
+% Environments |loosespacing| and |tightspacing| introduce four \meta{level}s of
+% \singlequotes{looseness} or \singlequotes{tightness}, where \meta{level}~=~0 disables the
+% functionalities. The higher the \meta{level} the looser or tighter the text will by typeset,
+% respectively.
+%
+% \begin{synopsis}\label{syn:loosespacing}
+% \cs{begin}|{loosespacing}|\oarg{level}
+% \dots{}
+% \cs{end}|{loosespacing}|
+% \end{synopsis}
+%
+% Environment~|loosespacing| increases the width of a space by the percentages given in the
+% \cref{tab:loosespacing}.
+%
+% \begin{SCtable}[10]
+% \caption[Spacing changes made by \code{loosespacing}]%
+% {Adjustments made by environment |loosespacing| to \cs{spaceskip}.
+% The mapping of \meta{level} to the exact skip definitions are
+% \(1 \mapsto \formatskip{1.05}{.5}{.1}\),
+% \(2 \mapsto \formatskip{1.1}{.5}{.1}\),
+% \(3 \mapsto \formatskip{1.2}{.6}{.2}\), and
+% \(\ge 4 \mapsto \formatskip{1.3}{.8}{.3}\),
+% where all factors scale with \cs{dimen2},
+% the current font's space-width.}
+% \label{tab:loosespacing}
+%
+% \begin{tabfigures}
+% \def~{\hphantom{0}}%
+% \begin{tabular}{@{}ccl@{}}
+% \toprule
+% \meta{level} & Adjustment & Comment \\
+% {} & \% & \\
+% \midrule
+% 0 & n/a & neutral \\
+% 1 & +5~ & default \\
+% 2 & +10 & \\
+% 3 & +20 & \\
+% \(\ge\)\:4 & +30 & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% The default level of |loosespacing| is~1.
+%
+% \begin{synopsis}\label{syn:tightspacing}
+% \cs{begin}|{tightspacing}|\oarg{level}
+% \dots{}
+% \cs{end}|{tightspacing}|
+% \end{synopsis}
+%
+% Environment~|tightspacing| decreases the width of a space by the percentages given in
+% \cref{tab:tightspacing}.
+%
+% \begin{SCtable}[10]
+% \caption[Spacing changes made by \code{tightspacing}]%
+% {Adjustments made by environment |tightspacing| to \cs{spaceskip}.
+% The mapping of \meta{level} to the exact skip definitions are
+% \(1 \mapsto \formatskip{.9875}{.0125}{.5\hphantom{000}}\)\!,
+% \(2 \mapsto \formatskip{.975}{.025}{.5\hphantom{00}}\)\!,
+% \(3 \mapsto \formatskip{.95}{.05}{.5\hphantom{0}}\)\!, and
+% \(\ge 4 \mapsto \formatskip{.9}{.1}{.5}\),
+% where all factors scale with \cs{dimen2},
+% the current font's space-width.}
+% \label{tab:tightspacing}
+%
+% \begin{tabfigures}
+% \def~{\hphantom{0}}%
+% \begin{tabular}{@{}ccl@{}}
+% \toprule
+% \meta{level} & Adjustment & Comment \\
+% {} & \% & \\
+% \midrule
+% 0 & n/a & neutral \\
+% 1 & ~{-}1.25 & default \\
+% 2 & ~{-}2.5~ & \\
+% 3 & ~{-}5\hphantom{.00} & \\
+% \(\ge\)\:4 & -10\hphantom{.00} & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% The default level of |tightspacing| is~1.
+%
+% \begin{note}
+% At a given \meta{level} the changes of |loosespacing| are much larger than those of
+% |tightspacing|.
+% \end{note}
+%
+% \begin{usecases}
+% Nudge line breaks or hyphenation points.~\visualpar Separate clashing descenders and
+% ascenders.~\visualpar Eliminate rivers.
+% \end{usecases}
+%
+%
+% \subsubsection{Wide Space}\label{sec:wide-space}\index{wide space}
+%
+% The \cs{widespace} macro and its companion \cs{narrowspace} derive their appearances from
+% several of the current font's \cs{fontdimen}\meta{number}s. \TeX{} addresses the latter by
+% integers, which is totally non-memnonic. Therefore, we play softball by first presenting
+% \cref{tab:fontdimen} that associates the \cs{fontdimen}\meta{number}s with their meanings and
+% also reports on their current values (for this document).\footnote{The association is given
+% in Appendix~F (p.~433) of Ref.~\citenum{knuth:1986}. For a concise and understandable
+% explanation of the \TeX~\cs{fontdimen} parameters consult Ref.~\citenum{carlisle:2013}.}
+%
+% \begin{SCtable}
+% \caption[\cs{fontdimen}\meta{number} parameters]
+% {The first column~\sample{\#} states the index of the \cs{fontdimen} parameter:
+% \meta{number}. Column~2 presents short descriptions of the
+% \cs{fontdimen}\meta{number} parameters. As examples, the values for the current
+% font are shown in column~3; they are normalized to the quad-size.\bottomstrut}
+% \label{tab:fontdimen}
+%
+% \begin{tabfigures}
+% \def~{\hphantom{0}}%
+% \ExplSyntaxOn
+% \def\straightfontdimen#1{\fp_eval:n {\the\fontdimen#1\font}}
+% \def\roundfontdimen#1{\fp_eval:n {round (1000 * \the\fontdimen#1\font) / 1000}}
+% \def\relativefontdimen#1{\fp_eval:n {round (1000 * \the\fontdimen#1\font / \the\fontdimen6\font) / 10}}
+% \ExplSyntaxOff
+%
+% \begin{tabular}{@{}lll@{}}
+% \toprule
+% \# & Description & Value \\
+% {} & & \multicolumn{1}{c}{\%} \\
+% \midrule
+% 1 & Slant per 1\,pt height & ~~\relativefontdimen1\topstrut \\
+% 2 & Interword space width & ~\relativefontdimen2 \\
+% 3 & Interword stretch & ~\relativefontdimen3 \\
+% 4 & Interword shrink & ~~\relativefontdimen4 \\
+% 5 & \sample{\itcorr{2}x\itcorr{2}} height & ~\relativefontdimen5 \\
+% 6 & \cs{quad} height & \relativefontdimen6 \\
+% 7 & Extra space width & ~~\relativefontdimen7 \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% \DescribeMacro{\widespace}
+% \DescribeMacro{\widespace*}
+% \sinceversion{Starred form since v0.2}
+% Typeset a wide, sentence-ending space as if in \cs{nonfrenchspacing}~mode. Consult
+% \Cref{tab:space-sizes} for a comparison of the various sizes.
+%
+% \begin{synopsis}\label{syn:widespace}
+% \cs{widespace} \\
+% \cs{widespace*}
+% \end{synopsis}
+%
+% The unstarred macro~\cs{widespace} inserts a space that is as wide as the font's
+% sentence-ending space in \cs{nonfrenchspacing}~mode, this is
+% \begin{equation*}
+% |\fontdimen2| + \cs{widespacestrength} \times |\fontdimen7|.
+% \end{equation*}
+%
+% \noindent
+% Its width is independent of any \cs{frenchspacing} or \cs{nonfrenchspacing}~settings, but
+% depends on \cs{widespacestrength} which defaults
+% to~\widespacestrength\widespace\marginnote{The sentence that ends with
+% \singlequotes{\widespacestrength} uses \cs{widespace} after the period.} The latter can be
+% overridden by the user to get a more or less pronounced effect.
+%
+% If |\fontdimen7| happens to be zero \cs{widespace} uses
+% \begin{equation*}
+% \cs{widespacescale} \times |\fontdimen2|
+% \end{equation*}
+%
+% \noindent
+% as width instead, where \cs{widespacescale} defaults to \widespacescale. The stretchability
+% and shrinkability of \cs{widespace} always are scaled with \cs{widespacescale}. The
+% \cs{widespacescale} too can be redefined by the user to achieve different effects.
+%
+% The starred form, \cs{widespace*}, unconditionally uses the \(|\fontdimen7| = 0\) code-path.
+%
+% \begin{usecase}
+% Useful as a sentence-ending space if, for example, the sentence ends in an abbreviation
+% with a period or decimal number without trailing digits \emph{and} the next sentence should
+% be delimited in a clearer way.~\visualpar Open tight lines with a series
+% of~\cs{widespace}s.\footnote{\label{fn:widespace}See also \doublequotes{Investigating the
+% badness of a paragraph} on \Cpageref{sec:investigating-paragraph-badness}.}
+% \end{usecase}
+%
+%
+% \subsubsection{Narrow Space}\label{sec:narrow-space}\index{narrow space}
+%
+% \DescribeMacro{\narrowspace}
+% \DescribeMacro{\narrowspace*}
+% \sinceversion{Since v0.2}
+% Typeset a narrow space. Consult \Cref{tab:space-sizes} for a comparison of the various
+% sizes.
+%
+% \begin{synopsis}\label{syn:narrowspace}
+% \cs{narrowspace} \\
+% \cs{narrowspace*}
+% \end{synopsis}
+%
+% The unstarred macro~\cs{narrowspace} inserts a narrow space with the width
+% \begin{equation*}
+% |\fontdimen2| - \cs{narrowspacestrength} \times |\fontdimen7|
+% \end{equation*}
+%
+% \noindent
+% if |\fontdimen7| is different from zero or otherwise
+% \begin{equation*}
+% \cs{narrowspacescale} \times |\fontdimen2|.
+% \end{equation*}
+%
+% \noindent
+% The starred version, \cs{narrowspace*}, unconditionally uses the \(\cs{fontdimen7} = 0\)
+% code-path. Refer to \Cref{tab:fontdimen} for the meanings of the various
+% \cs{fontdimen}~parameters.
+%
+% The stretchability and shrinkability of \cs{narrowspace} always get scaled with
+% \cs{narrowspacescale}. Both factors, \cs{narrowspacestrength} and \cs{narrowspacescale} can
+% be redefined by the user; their defaults are \narrowspacestrength{} and \narrowspacescale,
+% respectively.
+%
+% \begin{usecase}
+% Tighten loose lines with a series of~\cs{narrowspace}s.\footnote{Footnote
+% \ref{fn:widespace} again applies.}
+% \end{usecase}
+%
+% \begin{table}
+% \centering
+% \caption[Comparison of some space sizes]
+% {Exemplary comparison of standard \cs{space} versus \cs{narrowspace} and
+% \cs{widespace}. All values are relative to the size of the current font's quad
+% size. \cs{narrowspace} and \cs{widespace} use the package's defaults.~\visualpar
+% The upper values in the Width-column for \cs{narrowspace}, and \cs{widespace}
+% refer to the \(\cs{fontdimen7} \not= 0\) case and the lower ones to the
+% \(\cs{fontdimen7} = 0\) code-path.}
+% \label{tab:space-sizes}
+%
+% \begin{tabfigures}
+% \def~{\hphantom{0}}%
+% \ExplSyntaxOn
+% \def\relativedimen#1{\fp_eval:n {round (1000 * (#1) / \the\fontdimen6\font) / 10}}
+% \def\relativefontdimen#1{\relativedimen{\the\fontdimen#1\font}}
+% \ExplSyntaxOff
+% \def\nrows{1.75}
+%
+% \begin{tabular}{@{}llll@{}}
+% \toprule
+% Name & Width & Stretch & Shrink \\
+% {} & \% & \% & \% \\
+% \midrule
+% \multirow{\nrows}{*}{\cs{narrowspace}} &
+% \relativedimen{\the\fontdimen2\font - \narrowspacestrength * \the\fontdimen7\font} &
+% \multirow{\nrows}{*}{\relativedimen{\narrowspacescale * \the\fontdimen3\font}} &
+% \multirow{\nrows}{*}{\relativedimen{\narrowspacescale * \the\fontdimen4\font}} \\[-.25\normalbaselineskip]
+% {} & \relativedimen{\narrowspacescale * \the\fontdimen2\font} & & \\
+% \cs{space} & \relativefontdimen2 & \relativefontdimen3 & \relativefontdimen4 \\
+% \multirow{\nrows}{*}{\cs{widespace}} &
+% \relativedimen{\the\fontdimen2\font + \widespacestrength * \the\fontdimen7\font} &
+% \multirow{\nrows}{*}{\relativedimen{\widespacescale * \the\fontdimen3\font}} &
+% \multirow{\nrows}{*}{\relativedimen{\widespacescale * \the\fontdimen4\font}} \\[-.25\normalbaselineskip]
+% {} & \relativedimen{\widespacescale * \the\fontdimen2\font} & & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{table}
+%
+%
+% \subsection{\packagename{Microtype} Front\capitalhyphen End}\label{sec:microtype-frontend}
+% \index{microtype=\packagename{microtype} (package)}
+%
+% The functionalities are just front-ends of selected macros in
+% package~\packagename{microtype} -- welcome syntactic sugar.
+%
+% \begin{important}
+% All macros and environments introduced in this section require that
+% package~\packagename{microtype}~\cite{package:microtype} has been loaded, preferably
+% \emph{before} package~\packagename{typog}
+%
+% \begin{codeexample}
+% \cs{usepackage}[\meta{microtype-options}\dots]\{microtype\} \\
+% \cs{usepackage}[\meta{typog-options}\dots]\{typog\}
+% \end{codeexample}
+%
+% \noindent
+% in the document preamble.
+% \end{important}
+%
+%
+% \subsubsection{Tracking}\label{sec:tracking-control}\index{font>tracking}
+%
+% \begin{caution}
+% The tracking changes may interfere with implicit changes of tracking declared with
+% \cs{SetTracking}. Explicit calls to \cs{textls} remain in effect.
+% \end{caution}
+%
+% \noindent
+% \DescribeEnv{setfonttracking}
+% Override the default tracking for all fonts.
+%
+% \begin{synopsis}\label{syn:setfonttracking}
+% \cs{begin}|{setfonttracking}|\marg{delta} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{setfonttracking}|
+% \end{synopsis}
+%
+% The environment~|setfonttracking| manages a group for \cs{lsstyle} of
+% package~\packagename{microtype}. The change \meta{delta} in tracking is given as multiples
+% of \nativetextfraction{1}{1000}\,em. Positive as well as negative values of \meta{delta} are
+% allowed.
+%
+% See Sec.~5.3, \singlequotes{Tracking}, and~7, \doublequotes{Letterspacing revisited}, in the
+% documentation of \packagename{microtype}~\cite{package:microtype} for a detailed explanation.
+%
+% For font combinations involving monospaced fonts (\TeX{} lingo: typewriter) an overly large
+% spacing may show up at the borders where fonts change. This is caused by the calculation of
+% the \doublequotes{outer spacing} described in Sec.~5.3 of the \packagename{microtype}~manual.
+%
+% Use configuration variable~\hyperref[item:trackingttspacing]{\code{trackingttspacing}} to
+% reduce the outer spacing to a reasonable value either directly at package-load time
+%
+% \begin{codeexample}
+% \cs{usepackage}[trackingttspacing=\{250, 75, 50\}]\{typog\}
+% \end{codeexample}
+%
+% \noindent
+% or with the help of \cs{typogsetup} in the document \emph{preamble} (after loading
+% \packagename{microtype} and \packagename{typog})
+%
+% \begin{codeexample}
+% \cs{typogsetup}\{trackingttspacing=\{250, 75, 50\}\}
+% \end{codeexample}
+%
+% If the argument of option~\code{trackingttspacing} is omitted the outer spacing defaults to
+% \makeatletter\mbox{\typog@trackingttspacing}\makeatother.
+%
+% \begin{usecases}
+% Nudge line breaks or hyphenation points.~\visualpar Avoid clashes of descenders and
+% ascenders, e.\,g., for \cs{smash}ed symbols of inline math.~-- Think of
+% integrals.~\visualpar Control the length of the last line in a paragraph.
+% \end{usecases}
+%
+%
+% \subsubsection{Font Expansion}\label{sec:font-expansion-control}\index{font>expansion}
+%
+% \DescribeEnv{setfontshrink}
+% \DescribeEnv{setfontstretch}
+% Adjust the limits of either only stretchability or only shrinkability and zero the other
+% component, i.\,e., shrinkability and stretchability, respectively.
+%
+% \begin{synopsis}\label{syn:setfontshrink}\label{syn:setfontstretch}
+% \cs{begin}|{setfontshrink}|\marg{level}
+% \dots{}
+% \cs{end}|{setfontshrink}| \\
+% \cs{begin}|{setfontstretch}|\marg{level}
+% \dots{}
+% \cs{end}|{setfontstretch}|
+% \end{synopsis}
+%
+% A \meta{level} of zero is a no-op. \Cref{tab:setfontshrink-values,tab:setfontstretch-values}
+% summarize the values for |stretch| and |shrink| in these environments.
+%
+% \begin{SCtable}
+% \caption[Shrink values of \code{setfontshrink}]%
+% {\slightlysloppy[2] Preconfigured values for |shrink| inside of
+% environment~\code{setfontshrink}. Note that all |stretch| values are zero, so the fonts
+% only can shrink.}
+% \label{tab:setfontshrink-values}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}cccl@{}}
+% \toprule
+% \meta{level} & |stretch| & |shrink| & Comment \\
+% {} & \nativetextfraction{1}{1000}\,em & \nativetextfraction{1}{1000}\,em & \\
+% \midrule
+% 0 & n/a & n/a & no operation \\
+% 1 & 0 & \hphantom{0}\makeatletter\typog@shrink@i\makeatother & default \\
+% 2 & 0 & \makeatletter\typog@shrink@ii\makeatother & \\
+% 3 & 0 & \makeatletter\typog@shrink@iii\makeatother & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% \begin{SCtable}
+% \centering
+% \caption[Stretch values of \code{setfontstretch}]%
+% {\slightlysloppy[2] Preconfigured values for |stretch| inside of
+% environment~\code{setfontstretch}. Note that all |shrink| values are zero, so the fonts
+% only can stretch.}
+% \label{tab:setfontstretch-values}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}cccl@{}}
+% \toprule
+% \meta{level} & |stretch| & |shrink| \\
+% {} & \nativetextfraction{1}{1000}\,em & \nativetextfraction{1}{1000}\,em & \\
+% \midrule
+% 0 & n/a & n/a & no operation \\
+% 1 & \hphantom{0}\makeatletter\typog@stretch@i\makeatother & 0 & default \\
+% 2 & \makeatletter\typog@stretch@ii\makeatother & 0 & \\
+% 3 & \makeatletter\typog@stretch@iii\makeatother & 0 & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% The three (nonzero) shrink limits of \code{setfontshrink} can be configured with package
+% option~\hyperref[item:shrinklimits]{\code{shrinklimits}} and --~in the same way~-- the three
+% (nonzero) stretch limits of \code{setfontstretch} with package
+% option~\hyperref[item:stretchlimits]{\code{stretchlimits}}.
+%
+% \begin{usecases}
+% Nudge line breaks or hyphenation points.~\visualpar Control the length of the last line in
+% a paragraph.
+% \end{usecases}
+%
+% \noindent
+% \DescribeEnv{setfontexpand}
+% Manipulate both, |stretch| and |shrink|~values at the same time.
+%
+% \begin{synopsis}\label{syn:setfontexpand}
+% \cs{begin}|{setfontexpand}|\marg{level}
+% \dots{}
+% \cs{end}|{setfontexpand}|
+% \end{synopsis}
+%
+% \Cref{tab:setfontexpand-values} gives an overview of the values associated with \meta{level}.
+%
+% \begin{SCtable}
+% \caption[Shrink and stretch values of \code{setfontexpand}]%
+% {\slightlysloppy[2] Preconfigured values for |shrink| and |stretch| inside of
+% environment~\code{setfontexpand}. Note that both |shrink| and |stretch| values are
+% nonzero, so the fonts can shrink or expand.}
+% \label{tab:setfontexpand-values}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}cccl@{}}
+% \toprule
+% \meta{level} & |stretch| & |shrink| & Comment \\
+% {} & \nativetextfraction{1}{1000}\,em & \nativetextfraction{1}{1000}\,em & \\
+% \midrule
+% 0 & n/a & n/a & no operation \\
+% 1 & \hphantom{0}\makeatletter\typog@stretch@i\makeatother & \hphantom{0}\makeatletter\typog@stretch@i\makeatother & default \\
+% 2 & \makeatletter\typog@stretch@ii\makeatother & \makeatletter\typog@stretch@ii\makeatother & \\
+% 3 & \makeatletter\typog@stretch@iii\makeatother & \makeatletter\typog@stretch@iii\makeatother & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{SCtable}
+%
+% The six shrink and stretch limits of \code{setfontexpand} can be configured with package
+% options~\hyperref[item:shrinklimits]{\code{shrinklimits}}
+% and~\hyperref[item:stretchlimits]{\code{stretchlimits}}.
+%
+% \begin{notes}
+% \begin{itemize}[notopsep]
+% \item Environment~|setfontexpand| shares its
+% \hyperref[item:shrinklimits]{\code{shrinklimits}} with \code{setfontshrink} and its
+% \hyperref[item:stretchlimits]{\code{stretchlimits}} with \code{setfontstretch}.
+%
+% \item These environments do not nail down any font's expansion but only set up its
+% available range. See Sec.~3.3, \doublequotes{Font Expansion}, in the
+% \packagename{microtype} documentation~\cite{package:microtype}.
+%
+% Moreover, a text may not \singlequotes{respond} neither to \code{setfontshrink},
+% \code{setfontstretch}, nor~\code{setfontexpand} because \TeX{} already considers it
+% optimal without expansion or within the previous expansion limits, e.\,g., those set at
+% \packagename{microtype} load~time as opposed to \packagename{typog}'s
+% load~time.\specialsectionendhere
+% \end{itemize}
+% \end{notes}\unskip
+%
+% \begin{usecases}
+% Nudge line breaks or hyphenation points.~\visualpar Control the length of a paragraph,
+% e.\,g., to avoid a widow.
+% \end{usecases}
+%
+% \noindent
+% \DescribeEnv{nofontexpansion}
+% Disable the \packagename{microtype} feature~\singlequotes{expansion} inside of the
+% environment.
+%
+% \begin{synopsis}\label{syn:nofontexpansion}\label{syn:nofontexpand}
+% \cs{begin}|{nofontexpansion}|
+% \dots{}
+% \cs{end}|{nofontexpansion}| \\[\smallskipamount]
+% |nofontexpand|~(alias)
+% \end{synopsis}
+%
+% The name |nofontexpand| is an alias for~|nofontexpansion|.
+%
+% \begin{usecases}
+% Nudge line breaks or hyphenation points.~\visualpar Prevent severe scaling effects in
+% paragraphs strongly manipulated by other means, e.\,g.,
+% \hyperref[syn:shortenpar]{\code{shortenpar}}
+% or~\hyperref[syn:prolongpar]{\code{prolongpar}}.
+% \end{usecases}
+%
+%
+% \subsubsection{Character Protrusion}\label{sec:protrusion}\index{font>protrusion}
+%
+% \DescribeEnv{nocharprotrusion}
+% Disable the \packagename{microtype} feature~\singlequotes{protrusion} inside of the
+% environment.
+%
+% \begin{synopsis}\label{syn:nocharprotrusion}
+% \cs{begin}|{nocharprotrusion}|
+% \dots{}
+% \cs{end}|{nocharprotrusion}|
+% \end{synopsis}
+%
+% \begin{usecases}
+% Table of Contents or similar tables with aligned section numbers.~\visualpar Any table with
+% left- or right-aligned numerals in particular tabular numerals.~\visualpar Index.
+% \end{usecases}
+%
+%
+% \FloatBarrier
+% \subsection{Sloppy Paragraphs}\label{sec:sloppy-paragraphs}\index{paragraph>sloppy}
+%
+% Experienced \LaTeX{} users know that \cs{sloppy} is more of a problem by itself and not
+% really a viable solution of the \doublequotes{overfull~box} syndrome.
+%
+% \DescribeMacro{\slightlysloppy}
+% \DescribeEnv{slightlysloppypar}
+% We define the macro~\cs{slightlysloppy} and the associated environment,
+% \code{slightlysloppypar}, with a user-selectable \meta{sloppiness} parameter. The
+% constructions recover the known settings \cs{fussy} (\meta{sloppiness}~=~0) and \cs{sloppy}
+% (\meta{sloppiness}~\(\ge\)~8), and introduce seven intermediate
+% \meta{sloppiness}~levels.\footnote{Also compare the findings for \cs{emergencystretch} in
+% Ref.~\citenum{wermuth:2017a}.} The default \meta{sloppiness} is 1.
+%
+% \begin{synopsis}\label{syn:slightlysloppy}\label{syn:slightlysloppypar}
+% \cs{slightlysloppy}\oarg{sloppiness} \\[\smallskipamount]
+% \cs{begin}|{slightlysloppypar}|\oarg{sloppiness} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{slightlysloppypar}|
+% \end{synopsis}
+%
+% \Cref{tab:slightlysloppy} summarizes the adjustments that \cs{slightlysloppy} makes depending
+% on the \meta{sloppiness}~level.
+%
+% \begin{table}
+% \centering
+% \caption[Parameter adjustments of \cs{slightlysloppy}]%
+% {Adjustments made by \cs{slightlysloppy} to various \TeX~parameters at different
+% levels of \meta{sloppiness}.}
+% \label{tab:slightlysloppy}
+%
+% \newcommand*{\tolerancemark}{\tablenotemark{\dag}}%
+% \newcommand*{\scaledmark}{\tablenotemark{\ddag}}%
+%
+% \begin{suspendshortverb}
+% \begin{tabfigures}
+% \begin{tabular}{@{}ccccl@{}}
+% \toprule
+% \meta{sloppiness} & \cs{toler-} & \cs{hfuzz} & \cs{emergency-} & Comment \\
+% {} & \code{ance} & \cs{vfuzz} & \code{stretch}~\(G\) & \\
+% {} & & pt & em & \\
+% \midrule
+% 0 & \hphantom{0}200\hphantom{\tolerancemark} & .1\hphantom{0} & 0\hphantom{.000\scaledmark} & \TeX: \verb+\fussy+ \\
+% 1 & \hphantom{0}330\tolerancemark & .15 & \hphantom{0}.375\scaledmark & default \\
+% 2 & \hphantom{0}530\tolerancemark & .2\hphantom{0} & \hphantom{0}.75\scaledmark\hphantom{0} & \\
+% 3 & \hphantom{0}870\tolerancemark & .25 & 1.125\scaledmark & \\
+% 4 & 1410\tolerancemark & .3\hphantom{0} & 1.5\scaledmark\hphantom{00} & \\
+% 5 & 2310\tolerancemark & .35 & 1.875\scaledmark & \\
+% 6 & 3760\tolerancemark & .4\hphantom{0} & 2.25\scaledmark\hphantom{0} & \\
+% 7 & 6130\tolerancemark & .45 & 2.625\scaledmark & \\
+% \(\ge\)\:8 & 9999\hphantom{\tolerancemark} & .5\hphantom{0} & 3\hphantom{.000\scaledmark} & \TeX: \verb+\sloppy+ \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+% \end{suspendshortverb}
+%
+% \begin{tablenotes}
+% \tolerancemark\enspace
+% All intermediate levels set \(\cs{pretolerance} = \cs{tolerance} / 2\).
+%
+% \scaledmark\enspace
+% The intermediate levels scale the amount of available glue~\(G\) (indicated in column~4
+% of the table) for \cs{emergencystretch} with the actual line length, this means, in these
+% levels
+% \begin{equation*}
+% \cs{emergencystretch} = G \times \frac{\cs{linewidth}}{\cs{textwidth}}.
+% \end{equation*}
+% to prevent excessive stretchability in narrow lines.
+% \end{tablenotes}
+% \end{table}
+%
+% Environment~|slightlysloppypar|\oarg{sloppiness} mimics \LaTeX's~\code{sloppypar}, while
+% offering the flexibility of~\cs{slightlysloppy}.
+%
+% \begin{usecases}
+% Drop-in replacement for \cs{sloppy}, whether explicit or implicit (think of
+% \cs{parbox}).~\visualpar Initial paragraphs in theorem environments (e.\,g., as defined by
+% \packagename{amsmath} or \packagename{amsthm}), where the theorem~head already takes a lot
+% of space.~\visualpar Bibliographies as environment~\code{thebibliography} sets~\cs{sloppy}.
+% \end{usecases}
+%
+%
+% \FloatBarrier
+% \subsection{Vertically Partially-Tied Paragraphs}\label{sec:vtie-paragraph}\index{paragraph>vertically tied}
+%
+% \LaTeX{} provides several macros and environments to tie material vertically~-- most
+% prominently |samepage| and |minipage|.\footnote{A valuable complement to these is
+% package~\packagename{needspace}~\cite{package:needspace} which takes a different approach and
+% reliably works in \emph{mixed} horizontal and vertical mode situations.}
+% \packagename{Typog's} macros and environments constitute more sophisticated but weaker forms
+% of these. They tie only the first or last couple of lines in a paragraph while the rest of
+% the paragraph gets broken into pages by \TeX{} in the usual way.
+%
+% The macros and environments described in this section locally set \eTeX{} penalty
+% arrays~\cite[Sec.~3.8]{package:etex}. In addition the environments~\code{vtietoppar},
+% \code{vtiebotpar}, and~\code{vtiebotdisptoppar} explicitly issue a \cs{par} at the end of the
+% group.
+%
+% \DescribeMacro{\vtietop}
+% \DescribeEnv{vtietoppar}
+% Avoid a club\index{forlorn line>club} line in each partial paragraph.
+%
+% \begin{synopsis}\label{syn:vtietop}\label{syn:vtietoppar}
+% \cs{vtietop}\oarg{number-of-lines} \\[\smallskipamount]
+% \cs{begin}|{vtietoppar}|\oarg{number-of-lines}
+% \dots{}
+% \cs{end}|{vtietoppar}|
+% \end{synopsis}
+%
+% Vertically tie the first \meta{number\hyp{}of\hyp{}lines} in a paragraph. Zero or one for
+% \meta{number\hyp{}of\hyp{}lines} are no-ops. Up to nine lines can be fused. The default is
+% to link three lines.
+%
+% \begin{usecases}
+% String together the first paragraph right after a sectioning command.~\visualpar Tie the
+% first line of an itemized, enumerated, or a description list\index{list} with the paragraph
+% following~\cs{item}.
+% \end{usecases}
+%
+% \noindent
+% \DescribeMacro{\splicevtietop}
+% Inside of a \code{list} a one-off solution simply concatenates \cs{item}[\dots]\cs{vtietop}
+% to fuse the line with the \code{item\#}, the representation of the \code{enum\#}, or the
+% description term with the first paragraph. For a systematic use prefer \cs{splicevtietop}
+% and apply it as the first thing in the \code{list}~body.
+%
+% \begin{synopsis}\label{syn:splicevtietop}
+% \cs{splicevtietop}\oarg{number-of-lines}
+% \end{synopsis}
+%
+% Use this macro \emph{inside} of a \code{list}-like environment to equip each \cs{item} with
+% \cs{vtietop}\oarg{number-of-lines}. The default \meta{number-of-lines} is three as for any
+% of the \code{vtie\dots}~functions.
+%
+% Example for a \code{description}~list and plain \LaTeX:
+%
+% \begin{codeexample}
+% 12\=\kill
+% \cs{begin}\{description\} \\
+% \> \cs{splicevtietop}[2] \\
+% \> \cs{item}[...] \\
+% \cs{end}\{description\}
+% \end{codeexample}
+%
+% Alternatively with package~\packagename{enumitem}~\cite{package:enumitem}:
+%
+% \begin{codeexample}
+% 12\=\kill
+% \cs{begin}\= \{description\}[first=\cs{splicevtietop[2]}] \\
+% \> \cs{item}[...] \\
+% \cs{end}\{description\}
+% \end{codeexample}
+%
+% \noindent
+% or shorter and with the default \meta{number-of-lines},~3, using the \packagename{enumitem}
+% style\footnote{The documentation of \packagename{enumitem} prosaically calls them
+% \singlequotes{keys} (Section~3) not \singlequotes{styles}.}~\code{vtietop}:
+%
+% \DescribeEnumItemKey{vtietop}
+% \begin{codeexample}
+% \cs{usepackage}\{enumitem\} \\
+% \cs{begin}\= \{description\}[vtietop] \\
+% ~~\cs{item}[...] \\
+% \cs{end}\{description\}
+% \end{codeexample}
+%
+% \medskip
+%
+% \noindent
+% \DescribeMacro{\vtiebot}
+% \DescribeEnv{vtiebotpar}
+% Avoid a widow\index{forlorn line>widow} line in each partial paragraph.
+%
+% \begin{synopsis}\label{syn:vtiebot}\label{syn:vtiebotpar}
+% \cs{vtiebot}\oarg{number-of-lines} \\[\smallskipamount]
+% \cs{begin}|{vtiebotpar}|\oarg{number-of-lines}
+% \dots{}
+% \cs{end}|{vtiebotpar}|
+% \end{synopsis}
+%
+% Vertically tie the last \meta{number\hyp{}of\hyp{}lines} in a paragraph. Zero or one for
+% \meta{number\hyp{}of\hyp{}lines} are no-ops. Up to nine lines can be fused. The default is
+% to link three lines.
+%
+% \noindent
+% \DescribeEnv{vtiebotdisp}
+% Avoid a display widow\index{forlorn line>display widow} line in each partial paragraph.
+%
+% \begin{synopsis}\label{syn:vtiebotdisp}\label{syn:vtiebotdisppar}
+% \cs{begin}|vtiebotdisp|\oarg{before-disp-number-of-lines} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{vtiebotdisp}|
+% \end{synopsis}
+%
+% Vertically tie the last \meta{before\hyp{}disp\hyp{}number\hyp{}of\hyp{}lines} in a paragraph
+% before a display. Zero or one for \meta{before\hyp{}disp\hyp{}number\hyp{}of\hyp{}lines} are
+% no-ops. Up to nine lines can be fused. The default is to link three lines.
+%
+% To use the function bracket the paragraph before the display (the one that needs protection)
+% and the associated displayed math:
+%
+% \begin{codeexample}
+% \cs{begin}\{vtiebotdisp\} \\
+% ~~\% vertically tied paragraph before the math display \\
+% ~~\cs{begin}\{equation\} \\
+% ~~~~\% math \\
+% ~~\cs{end}\{equation\} \\
+% \cs{end}\{vtiebotdisp\}
+% \end{codeexample}
+%
+% \DescribeEnv{vtiebotdisptoppar}
+% Avoid a display widow, compound the display with its preceding \emph{and} following
+% paragraph, and avoid a club line in the paragraph right after the display.
+%
+% \begin{synopsis}\label{syn:vtiebotdisptop}\label{syn:vtiebotdisptoppar}
+% \begin{tabbing}
+% \cs{begin}|{vtiebotdisptoppar}|\= \oarg{before-disp-number-of-lines} \\
+% \> \oarg{after-disp-number-of-lines} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{vtiebotdisptoppar}|
+% \end{tabbing}
+% \end{synopsis}
+%
+% Vertically tie the last \meta{before\hyp{}disp\hyp{}number\hyp{}of\hyp{}lines} in the
+% paragraph before a display and the first
+% \meta{after\hyp{}disp\hyp{}number\hyp{}of\hyp{}lines} in the paragraph after the display.
+% Moreover, turn the paragraphs and the display into an un-breakable unit.\footnote{The
+% paragraphs and the display are concreted together by setting both \cs{predisplaypenalty}
+% and~\cs{postdisplaypenalty} to~10000.}
+%
+% Zero or one for \meta{before-disp-number\hyp{}of\hyp{}lines} as well as
+% \meta{after\hyp{}disp\hyp{}number\hyp{}of\hyp{}lines} are no-ops for the respective
+% paragraph. Up to nine lines each can be fused.
+%
+% Both optional arguments default to three. If only the first argument is given the second
+% acquires the same value.
+%
+%
+% To use the function bracket the paragraphs before and after the display:
+%
+% \begin{codeexample}
+% \cs{begin}\{vtiebotdisptoppar\} \\
+% ~~\% vertically tied paragraph before the math display \\
+% ~~\cs{begin}\{equation\} \\
+% ~~~~\% math \\
+% ~~\cs{end}\{equation\} \\
+% ~~\% vertically tied paragraph after the math display \\
+% \cs{end}\{vtiebotdisptoppar\}
+% \end{codeexample}
+%
+% \smallskip
+%
+% \noindent
+% See also \cref{sec:fill-last-line-gp-environments} for other methods to avoid club or widow
+% lines.
+%
+% \begin{typoginspectpar}{partial-paragraphs}
+% \setlength{\smoothraggedrightragwidth}{8pt}
+% \paragraph{Partial Paragraphs And Counting Lines.} The top-of-paragraph ties, \cs{vtietop}
+% and \code{vtietoppar} count \meta{number\hyp{}of\hyp{}lines} from the beginning of every
+% partial paragraph. Each displayed math in the paragraph resets the count. The
+% bottom-paragraph ties, \cs{vtiebot}, \code{vtiebotpar}, \cs{vtiebotdisp}, and
+% \code{vtiebotdisppar} count backward from the end of each partial paragraph. Again, each
+% displayed math in the paragraph resets the count. According to \TeX's rules, a displayed
+% math formula always is counted as \emph{three} lines no matter its contents.
+% \Cref{tab:partial-paragraph-line-counts} summarizes these rules with the help of an
+% example.
+% \end{typoginspectpar}
+%
+% \begin{table}
+% \centering
+% \caption[Partial paragraph line counts]
+% {Exemplary, eight-line paragraph compounded of two partial paragraphs of three and
+% two lines and a displayed math formula of arbitrary size sandwiched in between.}
+% \label{tab:partial-paragraph-line-counts}
+%
+% \newcommand*{\clubmark}{\tablenotemark{\dag}}
+% \newcommand*{\widowmark}{\tablenotemark{\ddag}}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}clcc@{}}
+% \toprule
+% Continuous & Example & \cs{vtietop}\clubmark & \cs{vtiebot}\widowmark \\
+% Line Number & Contents & Count & Count \\
+% \midrule
+% 1 & Text line\textsubscript{1} & 1 & 3 \\
+% 2 & Text line\textsubscript{2} & 2 & 2 \\
+% 3 & Text line\textsubscript{3} & 3 & 1 \\
+% 4 & & & \\
+% 5 & \(\smash{\Biggr\}}\) \parbox[c][0pt]{3.5em}{Display \\[-.12em] math} & & \\
+% 6 & & & \\
+% 7 & Text line\textsubscript{4} & 1 & 2 \\
+% 8 & Text line\textsubscript{5} & 2 & 1 \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+%
+% \begin{tablenotes}
+% \clubmark\enspace
+% This is \eTeX's counting scheme of \cs{clubpenalties}; it also holds for
+% \code{vtietoppar}.
+%
+% \widowmark\enspace
+% The same counting scheme also holds for \code{vtiebotpar}, \cs{vtiebotdisp},
+% and~\code{vtiebotdisppar}. It is implied by \eTeX's line counts of \cs{widowpenalties}
+% and~\cs{displaywidowpenalties} on which the functions of this package are based.
+% \end{tablenotes}
+% \end{table}
+%
+% \begin{tips}
+% \begin{itemize}[notopsep]
+% \item The environments can be combined to arrive at paragraphs that simultaneously are
+% protected against club lines and (display) widow lines.
+%
+% \item For very long derivations that are not interrupted and thus made breakable with the
+% help of \cs{intertext}\footnote{Introduced in
+% package~\packagename{amsmath}~\cite{package:amsmath}.} or
+% \cs{shortintertext}\footnote{Defined in
+% package~\packagename{mathtools}~\cite{package:mathtools}.} it is desirable to make the
+% display breakable. This is achieved with \cs{allowdisplaybreaks} or the
+% environment~\code{breakabledisplay} which will be described
+% in~\cref{sec:breakable-display}.\specialsectionendhere
+% \end{itemize}
+% \end{tips}\unskip
+%
+% \begin{usecases}
+% Fix widows and orphans, e.\,g., those turned up by
+% package~\packagename{widows-and-orphans}~\cite{package:widows-and-orphans}.~\visualpar
+% Extend the typographic convention of \doublequotes{three to four lines instead of a single
+% club or widow line} to a context-dependent number of lines that tries to keep all (well,
+% dream on) the information together the reader needs at that particular point.
+% \end{usecases}
+%
+%
+% \FloatBarrier
+% \subsection{Breakable Displayed Equations}\label{sec:breakable-display}\index{page break}
+%
+% \DescribeEnv{breakabledisplay}
+% Package~\packagename{amsmath}\index{amsmath=\packagename{amsmath} (package)} offers
+% \cs{allowdisplaybreaks} to render displayed equations breakable at each of their lines.
+% Environment~\cs{breakabledisplay} is a wrapper around it which limits the macro's influence
+% to the environment. Furthermore, the default \meta{level} of \code{breakabledisplay} is~3
+% whereas that of \cs{allowdisplaybreaks} is~4. This makes \code{breakabledisplay} less eager
+% to break a displayed equation and thus better suited to full automation of the page-breaking
+% process.
+%
+% \begin{synopsis}\label{syn:breakabledisplay}
+% \cs{begin}|{breakabledisplay}|\oarg{level} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{breakabledisplay}|
+% \end{synopsis}
+%
+% Environment~|breakabledisplay| simply passes on \meta{level} to \cs{allowdisplaybreaks}.
+% \Cref{tab:allowdisplaybreaks-penalties} shows the default penalties that
+% \packagename{amsmath} associated with each of the \meta{level}s.
+%
+% \begin{table}
+% \centering
+% \caption[Env.~\code{breakabledisplay} and \cs{interdisplaylinepenalty}]%
+% {Penalties~\cs{interdisplaylinepenalty} associated with different \meta{level}s of
+% environment~\code{breakabledisplay}. Depending on the version of
+% package~\packagename{amsmath} the actual penalties may differ.}
+% \label{tab:allowdisplaybreaks-penalties}
+%
+% \newcommand*{\clubmark}{\tablenotemark{\dag}}
+%
+% \begin{tabfigures}
+% \begin{tabular}{@{}ccl@{}}
+% \toprule
+% \meta{level} & \cs{interdisplay-} & Comment \\
+% {} & \code{linepenalty} & \\
+% \midrule
+% 0 & 10000 & no operation \\
+% 1 & \hphantom{0}9999 & \\
+% 2 & \hphantom{0}6999 & \\
+% 3 & \hphantom{0}2999 & default \\
+% 4 & \hphantom{0000}0\rlap{\clubmark} & \\
+% \bottomrule
+% \end{tabular}
+% \end{tabfigures}
+%
+% \begin{tablenotes}
+% \clubmark\enspace
+% This is the default of \cs{allowdisplaybreaks}.
+% \end{tablenotes}
+% \end{table}
+%
+% \begin{tips}
+% \begin{itemize}[notopsep]
+% \item Terminating a line with \code{\textbackslash\textbackslash*} inhibits a break after
+% this line.
+%
+% \item A \cs{displaybreak}\oarg{level} can be set for \emph{each} line of the displayed
+% equation separately. \LaTeX{} resumes with the original value of
+% \cs{interdisplaylinepenalty} in the following lines.
+%
+% \item If a discretionary break of the displayed equation is to be accompanied with some aid
+% for the reader, team \cs{intertext} (or \cs{shortintertext}) with \cs{displaybreak} as,
+% e.\,g.,
+%
+% \begin{codeexample}
+% \cs{newcommand*}\{\cs{discretionarydisplaybreak}\} \\
+% 12\=3\=\kill
+% \> \{ \> \cs{intertext}\{\cs{hfill} Eq.\textasciitilde cont.\textasciitilde on next page.\}\% \\
+% \> \> \cs{displaybreak} \\
+% \> \> \cs{intertext}\{Eq.\textasciitilde cont.\textasciitilde
+% from prev.\textasciitilde page.\cs{hfill}\}\}\specialsectionendhere
+% \end{codeexample}
+% \end{itemize}
+% \end{tips}\unskip
+%
+% \begin{usecases}
+% Extremely long derivations without interspersed \cs{intertext} or
+% \cs{shortintertext}.~\visualpar Draft phase of a document.
+% \end{usecases}
+%
+%
+% \FloatBarrier
+% \clearpage
+% \subsection{\packagename{Setspace} Front-End}\label{sec:setspace-frontend}
+%
+% Package \packagename{setspace} \cite{package:setspace} is a base hit when it comes to
+% consistently setting the line skip for a document via the macro~\cs{setstretch}. The
+% interface of \cs{setstretch} though is unintuitive as it asks for an obscure
+% factor.\fontsizeinfo{setspacefontsizeinfo}\marginnote{In the copy of this document gets
+% typeset with~\setspacefontsizeinfo*.} The \LaTeX{} user however prefers to keep her eyes on
+% the ball and set the line skip\index{baseline skip} directly (e.\,g.~12.5pt) or the lines'
+% leading\index{leading} to a length or percentage of the font's size.\footnote{To find out
+% about the current font's size and the \cs{baselineskip} in printable form check out
+% \cref{sec:font-information} on \cpageref{sec:font-information}.} This is where the following
+% macros go to bat.
+%
+% \begin{important}
+% All macros that are introduced in this section rely on macro~\cs{setstretch}. So
+% package~\packagename{setspace} must have been loaded with
+%
+% \begin{codeexample}
+% \cs{usepackage}\{setspace\}
+% \end{codeexample}
+%
+% \noindent
+% in the document preamble.
+% \end{important}
+%
+% \DescribeMacro{\setbaselineskip}
+% \sinceversion{Since v0.3}
+% Set the line skip using an absolute length -- technically: a |dimen|.
+%
+% \begin{synopsis}\label{syn:setbaselineskip}
+% \cs{setbaselineskip}\marg{baseline-skip}
+% \end{synopsis}
+%
+% Set the \cs{baselineskip} to \meta{baseline-skip}. This is what a non-initiated user expects
+% from the assignment
+%
+% \begin{codeexample}
+% \cs{setlength}\{\cs{baselineskip}\}\{\meta{baseline-skip}\}
+% \end{codeexample}
+%
+% The \meta{baseline-skip} can contain a rubber (stretch/shrink) component, however,
+% \cs{setbaselineskip} will discard of it and issue a warning that only the fixed-length part
+% will be used in the computation.
+%
+% \begin{example}
+% Let us assume we want to lighten the gray value of the copy a tad with a \cs{baselineskip}
+% increased (from e.g.~12pt) to~12.5pt. To this end we say:
+%
+% \begin{codeexample}
+% \cs{setbaselineskip}\{12.5pt\}\specialsectionendhere
+% \end{codeexample}
+% \end{example}
+%
+% \begin{tip}
+% To set the \cs{baselineskip} relative to the current value use
+%
+% \begin{codeexample}
+% \cs{setbaselineskip}\{\meta{factor}\cs{baselineskip}\}
+% \end{codeexample}
+%
+% \noindent
+% where \meta{factor} is a floating-point number.
+% \end{tip}
+%
+% \DescribeMacro{\resetbaselineskip}
+% \sinceversion{Since v0.3}
+% Reset the \cs{baselineskip} to its original value.
+%
+% \begin{synopsis}\label{syn:resetbaselineskip}
+% \cs{resetbaselineskip}
+% \end{synopsis}
+%
+% This macro simply expands to |\setstretch{1}|. So, we rely on \packagename{setspace}'s
+% notion of what is a single-line \cs{baselineskip}.
+%
+%
+% \DescribeMacro{\setbaselineskippercentage}
+% \sinceversion{Since v0.3}
+% Set the \cs{baselineskip} with a relative value calculated as a percentage of the current
+% font's design size.
+%
+% \begin{synopsis}\label{syn:setbaselineskippercentage}
+% \cs{setbaselineskippercentage}\marg{baselineskip-percentage}
+% \end{synopsis}
+%
+% Set \cs{baselineskip} to \(\cs{typogfontsize} \times \meta{baselineskip-percentage} / 100\).
+%
+% \begin{example}
+% We modify the previous example and assume a font design size of 10pt, but now write
+%
+% \begin{codeexample}
+% \cs{setbaselineskippercentage}\{125\}
+% \end{codeexample}
+%
+% \noindent
+% which sets \cs{baselineskip} to \(10\text{pt} \times 125 / 100 = 12.5\text{pt}\).
+% \end{example}
+%
+% \DescribeMacro{\setleading}
+% \sinceversion{Since v0.3}
+% Set the \cs{baselineskip} with an absolute length that gets \emph{added to} \cs{typogfontsize}.
+%
+% \begin{synopsis}\label{syn:setleading}
+% \cs{setleading}\marg{leading}
+% \end{synopsis}
+%
+% Set the \cs{baselineskip} to \cs{typogfontsize} plus \meta{leading}. Note that
+% \meta{leading} can be negative, e.\,g.~to set solid.
+%
+% \begin{example}
+% Another solution of the previous example, given a font design size of 10pt is to write
+%
+% \begin{codeexample}
+% \cs{setleading}\{2.5pt\}
+% \end{codeexample}
+%
+% \noindent
+% which sets \cs{baselineskip} to \(10\text{pt} + 2.5\text{pt} = 12.5\text{pt}\).
+% \end{example}
+%
+% \DescribeMacro{\setleadingpercentage}
+% \sinceversion{Since v0.3}
+% Set the \cs{baselineskip} to \cs{typogfontsize} \emph{plus} a relative value calculated as a
+% percentage of \cs{typogfontsize}.
+%
+% \begin{synopsis}\label{syn:setleadingpercentage}
+% \cs{setleadingpercentage}\marg{leading-percentage}
+% \end{synopsis}
+%
+% Set \cs{baselineskip} to \(\cs{typogfontsize} \times (1 + \meta{leading-percentage} / 100)\).
+%
+% \begin{example}
+% We modify the previous example and again assume a font design size of 10pt, but now write
+%
+% \begin{codeexample}
+% \cs{setleadingpercentage}\{25\}
+% \end{codeexample}
+%
+% \noindent
+% which sets \cs{baselineskip} to \(10\text{pt} \times (1 + 25 / 100) = 12.5\text{pt}\).
+% \end{example}
+%
+% \smallskip
+%
+% \DescribeLaTeXDimen{\typogfontsize}
+% \sinceversion{Since v0.3}
+% The macros \cs{setbaselineskippercentage}, \cs{setleading}, and \cs{setleadingpercentage} all
+% depend on the font size. By changing \cs{typogfontsize} they can be configured for different
+% font sizes.
+%
+% The length \cs{typogfontsize} gets initialized at the end of the preamble to the default
+% font's quad size:\footnote{For an overview of the various
+% \cs{fontdimen}\meta{number}~parameters consult \cref{tab:fontdimen} on
+% \cpageref{tab:fontdimen}.}
+%
+% \begin{codeexample}
+% \cs{typogfontsize}=\cs{fontdimen6}\cs{font}
+% \end{codeexample}
+%
+% \noindent
+% which is also called its \doublequotes{nominal size} or its \doublequotes{design size}. This
+% assignment can be repeated at any point in the document to record a reference font's size.
+% To set just \cs{typogfontsize} without changing the current font, encapsulate the font change
+% in a group and export the new value:
+%
+% \begin{codeexample}
+% \cs{begingroup} \\
+% ~~\cs{usefont}\{T1\}\{Arvo-TLF\}\{m\}\{n\}\cs{selectfont} \\
+% ~~\cs{normalsize} \\
+% ~~\cs{global}\cs{typogfontsize}=\cs{fontdimen6}\cs{font} \\
+% \cs{endgroup}
+% \end{codeexample}
+%
+% An alternative to relying on the design size is using the actual size of an uppercase letter:
+%
+% \begin{codeexample}
+% \cs{settoheight}\{\cs{typogfontsize}\}\{CEMNORSUVWXZ\}
+% \end{codeexample}
+%
+% \noindent
+% With \cs{typogfontsize} defined this way it becomes trivial to set solid:
+%
+% \begin{codeexample}
+% \cs{setleading}\{0pt\}
+% \end{codeexample}
+%
+% \noindent
+% or
+%
+% \begin{codeexample}
+% \cs{setleadingpercentage}\{0\}
+% \end{codeexample}
+%
+% \begin{tip}
+% All macros in this section actually accept expressions of their respective argument types,
+% though the sick rules of \TeX{} \meta{dimen}- and \meta{skip}-expressions apply.
+%
+% Here are some forms that do work:
+%
+% \begin{codeexample}
+% \cs{setbaselineskip}\{12pt + 0.6667pt\} \\
+% \cs{setbaselineskip}\{12pt * 110 / 100\} \\
+% \cs{setbaselineskippercentage}\{100 + 25\} \\
+% \cs{setleading}\{1pt / -2.0\} \\
+% \cs{setleadingpercentage}\{10 - 25 / 2\}\specialsectionendhere
+% \end{codeexample}
+% \end{tip}
+%
+%
+% \FloatBarrier
+% \clearpage
+% \subsection{Smooth Ragged}\label{sec:smooth-ragged}\index{ragged right}
+%
+% \begin{whittyquote}
+% The attention someone gives \\
+% to what he or she makes \\
+% is reflected in the end result, \\
+% whether it is obvious or not. \\
+% \capitalemdash*~\propername{Erik Spiekermann}
+% \end{whittyquote}
+%
+% \noindent
+% Package \packagename{typog} implements a novel approach to typeset ragged paragraphs.
+% Instead of setting the glue inside of a paragraph to zero and letting the line-widths vary
+% accordingly~\cite{wermuth:2020} we prescribe the line-widths with the \cs{parshape}~primitive
+% and leave alone the stretchability or shrinkability of the glue.
+%
+% \begin{slightlysloppypar}
+% \hangindent=5.5em\hangafter=-5
+% \DescribeEnv{smoothraggedrightshapetriplet}
+% \DescribeEnv{smoothraggedrightshapequintuplet}
+% \DescribeEnv{smoothraggedrightshapeseptuplet}
+% We introduce three environments that allow for setting three, five, or seven different
+% line-lengths: \code{smoothraggedrightshapetriplet},
+% \code{smoothraggedrightshapequintuplet}, and \code{smoothraggedrightshapeseptuplet}; they
+% work for paragraphs up to
+% \makeatletter
+% \typog@triplet@max@lines, \typog@quintuplet@max@lines, or \typog@septuplet@max@lines~lines,
+% \makeatother
+% respectively.
+% \end{slightlysloppypar}
+%
+%
+% \begin{maxipage}
+% \begin{synopsis}\label{syn:smoothraggedrightshapetriplet}\label{syn:smoothraggedrightshapequintuplet}\label{syn:smoothraggedrightshapeseptuplet}
+% \cs{begin}|{smoothraggedrightshapetriplet}|\oarg{option\dots}\marg{width1}\marg{width2}\marg{width3} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{smoothraggedrightshapetriplet}| \\[\smallskipamount]
+% \cs{begin}|{smoothraggedrightshapequintuplet}|\oarg{option\dots}\marg{width1}\marg{width2}\dots\marg{width5} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{smoothraggedrightshapequintuplet}| \\[\smallskipamount]
+% \cs{begin}|smoothraggedrightshapeseptuplet|\oarg{option\dots}\marg{width1}\marg{width2}\dots\marg{width7}
+% \hspace*{1em}\dots \\
+% \cs{end}|{smoothraggedrightshapeseptuplet}|
+% \end{synopsis}
+% \end{maxipage}
+%
+% The environments take \(N\) = 3, 5, or~7 mandatory line-width parameters, where each
+% \meta{width\itcorr{3}I}, \(I = 1,\dots, N\) is a skip, i.\,e.,~a dimen that can include some
+% glue.
+%
+%
+% \paragraph{Options}
+%
+% \begin{description}[style=nextline]
+% \item[|leftskip=|\meta{dim}]
+% Set the left margin for the smooth ragged paragraph to \meta{dim}. Similar to the \TeX{}
+% parameter~\cs{leftskip}.
+%
+% \item[|parindent=|\meta{dim}]
+% Set the first-line indent for the smooth ragged paragraph to \meta{dim}. Similar to the
+% \TeX{} parameter~\cs{parindent}.
+% \end{description}
+%
+% \noindent
+% \DescribeEnv{smoothraggedrightpar}
+% Environment~|smoothraggedrightpar| builds upon the three generators. It typesets a single
+% paragraph with a given \meta{ragwidth} of the ragged, right margin, where the rag~width is
+% the length-difference of the longest and the shortest lines.
+%
+% \begin{synopsis}\label{syn:smoothraggedrightpar}
+% \cs{begin}|{smoothraggedrightpar}|\oarg{option\dots} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{smoothraggedrightpar}|
+% \end{synopsis}
+%
+% The line lengths equally divide the ragged margin, i.\,e., they are arithmetic means with
+% respect to the generator size.
+%
+% \iffalse
+%<*smoothparshapes>
+prologues := 3;
+
+def draw_filled_rectangle(expr lower_left, upper_right, color) =
+ fill lower_left -- (xpart upper_right, ypart lower_left) --
+ upper_right -- (xpart lower_left, ypart upper_right) --
+ cycle
+ withcolor color;
+enddef;
+
+
+u := 100;
+
+em := 10;
+linelength := 2u;
+baselineskip := 1.2em;
+parskip := 3;
+parindent := 2.5em;
+ragwidth := 2em;
+
+cmykcolor line_color;
+line_color := (.08, 0, 0, .18); % cold silver
+
+color customred[];
+customred[1] := (.890, .282, .282);
+customred[2] := (.831, .110, .110);
+customred[3] := (.686, .043, .043);
+customred[4] := (.569, .000, .000);
+customred[5] := (.420, .000, .000);
+
+color margin_color;
+margin_color := customred[2];
+
+
+beginfig(1); % triplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth/2, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth/2, y + 1em), line_color); % (2)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -5baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -5baselineskip), margin_color);
+endfig;
+
+
+beginfig(2); % quintuplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - .75ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .25ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .75ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .25ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -9baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -9baselineskip), margin_color);
+endfig;
+
+
+beginfig(3); % septuplet
+ y := 0;
+ draw_filled_rectangle((0, y), (linelength - .6667ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .1667ragwidth, y + 1em), line_color); % (6)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .3333ragwidth, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .8333ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (7)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (4)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .6667ragwidth, y + 1em), line_color); % (3)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .1667ragwidth, y + 1em), line_color); % (6)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - ragwidth, y + 1em), line_color); % (1)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .3333ragwidth, y + 1em), line_color); % (5)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .8333ragwidth, y + 1em), line_color); % (2)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength, y + 1em), line_color); % (7)
+ y := y - baselineskip;
+ draw_filled_rectangle((0, y), (linelength - .5ragwidth, y + 1em), line_color); % (4)
+
+ draw_filled_rectangle((-.667em, 1em), (-.333em, -13baselineskip), margin_color);
+ draw_filled_rectangle((linelength + .333em, 1em), (linelength + .667em, -13baselineskip), margin_color);
+endfig;
+end
+%</smoothparshapes>
+% \fi
+%
+% \begin{itemize}[noindent]
+% \item
+% \begin{minipage}[t]{\linewidth}
+% The triplet generator repeats a \emph{short~line -- long~line -- middle-length~line}
+% sequence. Shown below are two complete cycles.
+%
+% \begin{center}
+% \includegraphics{smooth-parshapes-1.mps}
+% \end{center}
+% \end{minipage}
+%
+% \item
+% \begin{minipage}[t]{\linewidth}
+% The quintuplet generator varies the theme of the triplets and avoids the
+% \singlequotes{ladder} of lines~2\figuredash3\figuredash4 (or, if numbered by
+% cycle:~1.2\figuredash1.3\figuredash2.1) there. Shown here are two cycles.
+%
+% \begin{center}
+% \includegraphics{smooth-parshapes-2.mps}
+% \end{center}
+% \end{minipage}
+%
+% \item
+% \begin{minipage}[t]{\linewidth}
+% The septuplet generator uses a permutation that looks \singlequotes{random}. At least it
+% hides the boundaries of cycles well. Shown here are two of them.
+%
+% \begin{center}
+% \includegraphics{smooth-parshapes-3.mps}
+% \end{center}
+% \end{minipage}
+% \end{itemize}
+%
+% \noindent
+% \DescribeEnv{smoothraggedright}
+% Environment~|smoothraggedright| is the multi-paragraph version of
+% \code{smoothraggedrightpar}. It takes the same optional arguments.
+%
+% \begin{synopsis}\label{syn:smoothraggedright}
+% \cs{begin}|{smoothraggedright}|\oarg{option\dots} \\
+% \hspace*{1em}\dots \\
+% \cs{end}|{smoothraggedright}|
+% \end{synopsis}
+%
+%
+% \paragraph{Options}
+%
+% \begin{description}[style=nextline]
+% \item[|linewidth=|\meta{dim}]
+% Override the length of the longest line. The default line-width is \cs{linewidth}.
+% \end{description}
+%
+%
+% \paragraph{Global Parameters}
+%
+% \begin{description}[style=nextline]
+% \item[\cs{smoothraggedrightfuzzfactor}=\meta{factor}]
+% The environment adds glue to every line-width\footnote{The shortest line only gets
+% stretchability, the longest only receives shrinkability. All other lines are both
+% stretchable and shrinkable.} to achieve a more convincing \doublequotes{ragged appearance}
+% and to reduce the number of overfull lines. The algorithm divides the smooth margin into
+% 3, 5, or~7 parts depending on the chosen \cs{smoothraggedrightgenerator} (see below). The
+% \cs{smoothraggedrightfuzzfactor} is the amount of glue of each line expressed as a multiple
+% of the distance between the division points. The default of 1.0 means to add as much glue
+% such that the lines just do not overlap (assuming justification is feasible).
+%
+% \item[\cs{smoothraggedrightgenerator}]
+% Select a generator to use. Valid generator names:
+% \begin{itemize}[noitemsep]
+% \item |triplet|,
+% \item |quintuplet|,
+% \item |septuplet|.
+% \end{itemize}
+%
+% The default generator is |triplet|.
+%
+% \item[\cs{smoothraggedrightleftskip}=\meta{dim}]
+% Value for |leftskip| to pass to the generator. Default:~0pt.
+%
+% \item[\cs{smoothraggedrightparindent}=\meta{dim}]
+% Value for |parindent| to pass to the generator. Default:~0pt.
+%
+% \item[\cs{smoothraggedrightragwidth}=\meta{dim}]
+% Value for the width of the ragged right margin. Default:~2em.
+% \end{description}
+%
+% \begin{usecases}
+% Replacement for \cs{RaggedRight}~\cite{package:ragged2e}.~\visualpar Design alternative for
+% fully justified paragraphs if used with a small rag-width.
+% \end{usecases}
+%
+%
+% \addtocontents{toc}{\par\bigskip\hfill\textit{Table of Contents continued on next page.}}
+% \addtocontents{toc}{\clearpage}
+%
+%
+% \sectionfinish
+% \clearpage
+% \section{Other Packages for Fine \LaTeX~Typography}\label{sec:other-typography-packages}
+%
+% Many other packages help with getting better output from \LaTeX. Here is a list --~in
+% alphabetical order~-- of the ones the author considers particularly valuable.
+%
+% \sbox{\listlabelbox}{\packagename{microtype}}
+% \begin{description}[font=\normalfont, labelsep*=1em, labelwidth=\wd\listlabelbox, leftmargin=!]
+% \item[\packagename{enumitem}]
+% Flexible and consistent definition of all basic \LaTeX-list types plus inline
+% lists~\cite{package:enumitem}.
+%
+% \item[\packagename{geometry}]
+% Powerful and sophisticated setup of the page layout~\cite{package:geometry}. Best
+% accompanied by \packagename{layout}~\cite{package:layout} to visualize the page geometries.
+%
+% \item[\packagename{hyphenat}]
+% Hyphens that do not inhibit further auto-hyphenation of a compound
+% word~\cite{package:hyphenat}.
+%
+% \item[\packagename{microtype}]
+% Fine control of spacing, tracking, sidebearings, character protrusion into the margins,
+% font expansion, and much more~\cite{package:microtype}.
+%
+% See also \propername{Khirevich's} discussion~\cite{khirevich:2013}.
+%
+% \item[\packagename{ragged2e}]
+% Improved versions of environments |raggedleft|, |raggedright|, and
+% |center|~\cite{package:ragged2e}.
+%
+% \item[\packagename{setspace}]
+% Consistently set the document's line-spacing, i.\,e.,
+% \cs{baselineskip}~\cite{package:setspace}.
+% \end{description}
+%
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+%
+% \MaybeStop{
+% \sectionfinish
+% \clearpage
+% \section{typog-grep}
+% \label{app:typog-grep}
+%
+% The companion program \programname{typog-grep} for analyzing the output of
+% \hyperref[syn:typoginspect]{\code{typoginspect}} and
+% \hyperref[syn:typoginspect]{\code{typoginspectpar}} has its own manual page. We reproduce
+% it here for completeness of the documentation.
+%
+% \begin{suspendshortverb}
+% \setlength{\parindent}{0pt}
+% \setlength{\parskip}{6.0pt plus 2.0pt minus .5pt}
+% \input typog-grep
+% \end{suspendshortverb}
+%
+% \sectionfinish
+% \clearpage
+% \phantomsection
+% \resetfancyhead
+% \addcontentsline{toc}{section}{Change History}
+% \PrintChanges
+%
+% \sectionfinish
+% \clearpage
+% \phantomsection
+% \addcontentsline{toc}{section}{References}
+% \begin{RaggedRight}
+% \begin{thebibliography}{88}
+% \bibitem{abrahams:2020}
+% \bibauthor{Abrahams, Paul~W.},
+% \bibauthor{Hargreaves, Kathryn~A.,} and
+% \bibauthor{Karl Berry}.
+% \bibtitle{\TeX{} for the Impatient}.
+% 2020,
+% \biburl{http://tug.ctan.org/info/impatient/book.pdf}.
+%
+% \bibitem{package:amsmath}
+% \bibauthor{American Mathematical Society} and the
+% \bibauthor{\LaTeXIII\ Project Team}.
+% \bibtitle{Package~\packagename{amsmath}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/amsmath}.
+%
+% \bibitem{package:cite}
+% \bibauthor{Arseneau, Donald}.
+% \bibtitle{Package~\packagename{cite}}.
+% 2015,
+% \biburl{https://ctan.org/pkg/cite}.
+%
+% \bibitem{package:enumitem}
+% \bibauthor{Bezos, Javier}.
+% \bibtitle{Package~\packagename{enumitem}}.
+% 2019,
+% \biburl{https://ctan.org/pkg/enumitem}.
+%
+% \bibitem{package:babel}
+% \bibauthor{Bezos, Javier}.
+% \bibtitle{Package~\packagename{babel}}.
+% 2021,
+% \biburl{https://ctan.org/pkg/babel}.
+% The original author of package~\packagename{babel} was \bibauthor{J. L. Braams}.
+%
+% \bibitem{package:etex}
+% \bibauthor{Breitenlohner, Peter} and
+% the \bibauthor{\(\mathcal{N\kern-.1em\raisebox{-.2em}{T}\kern-.1emS}\)~Team}.
+% \bibtitle{\eTeX}.
+% 1998,
+% \biburl{https://mirrors.ctan.org/systems/doc/etex/etex_man.pdf}.
+%
+% \bibitem{carlisle:1996}
+% \bibauthor{Carlisle, David}.
+% \bibtitle{Russian Paragraph Shapes}.
+% Baskerville, 6(1), 13\figuredash15,
+% 1996,
+% \biburl{http://uk-tug-archive.tug.org/wp-installed-content/uploads/2008/12/61.pdf}.
+%
+% \bibitem{carlisle:2013}
+% \bibauthor{Carlisle, David}.
+% \bibtitle{What do different \cs{fontdimen<num>} mean}.
+% 2013\figuredash*1\figuredash*2,
+% \biburl{https://tex.stackexchange.com/questions/88991/what-do-different-fontdimennum-mean}.
+%
+% \bibitem{package:cleveref}
+% \bibauthor{Cubitt, Toby}.
+% \bibtitle{Package~\packagename{cleveref}}.
+% 2018,
+% \biburl{https://ctan.org/pkg/cleveref}.
+%
+% \bibitem{eijkhout:2007}
+% \bibauthor{Eijkhout, Victor}.
+% \bibtitle{\TeX\ By Topic, A Texnician's Reference}.
+% 2007,
+% \biburl{https://www.eijkhout.net/tex/tex-by-topic.html}.
+%
+% \bibitem{package:mathtools}
+% \bibauthor{H{\o}gholm, Morten},
+% \bibauthor{Madsen, Lars} and
+% the \bibauthor{\LaTeXIII\ Project Team}.
+% \bibtitle{Package~\packagename{mathtools}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/mathtools}.
+%
+% \bibitem{khirevich:2013}
+% \bibauthor{Khirevich, Siarhei}.
+% \bibtitle{Tips on Writing a Thesis in \LaTeX}.
+% 2013,
+% \biburl{http://www.khirevich.com/latex/microtype}.
+%
+% \bibitem{knuth:1986}
+% \bibauthor{Knuth, Donald Ervin}.
+% \bibtitle{The \TeX{}book}.
+% Addison Wesley, Reading\kernedslash MA,
+% 1986.
+%
+% \bibitem{package:layout}
+% \bibauthor{McPherson, Kent}.
+% \bibtitle{Package~\packagename{layout}}.
+% 2014,
+% \biburl{https://ctan.org/pkg/layout}.
+% The package was converted to \LaTeXe\ by \bibauthor{J. L. Braams}
+% and modified by \bibauthor{H. Umeki}.
+%
+% \bibitem{middendorp:2014}
+% \bibauthor{Middendorp, Jan}.
+% \bibtitle{Shaping Text}.
+% \acronym{BIS}~publishers, Amsterdam,
+% 2014.
+%
+% \bibitem{mittelbach:2018c}
+% \bibauthor{Mittelbach, Frank}.
+% \bibtitle{Managing forlorn paragraph lines (a.\,k.\,a.~widows and orphans) in \LaTeX}.
+% TUGboat, 39(3), 246\figuredash251, 2018,
+% \biburl{https://tug.org/TUGboat/tb39-3/tb123mitt-widows.pdf}.
+%
+% \bibitem{package:widows-and-orphans}
+% \bibauthor{Mittelbach, Frank}.
+% \bibtitle{Package~\packagename{widows-and-orphans}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/widows-and-orphans}.
+%
+% \bibitem{package:hyperref}
+% \bibauthor{Rahtz, Sebastian,} and \bibauthor{Frank Mittelbach}.
+% \bibtitle{Package~\packagename{hyperref}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/hyperref}.
+% The package is maintained by the \LaTeXIII~Project Team.
+%
+% \bibitem{package:microtype}
+% \bibauthor{Schlicht, Robert}.
+% \bibtitle{Package~\packagename{microtype}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/microtype}.
+%
+% \bibitem{package:ragged2e}
+% \bibauthor{Schr\"oder, Martin}.
+% \bibtitle{Package~\packagename{ragged2e}}.
+% 2019,
+% \biburl{https://ctan.org/pkg/ragged2e}.
+%
+% \bibitem{solomon:1990}
+% \bibauthor{Solomon, David}.
+% \bibtitle{Output Routines: Examples and Techniques. Part~I: Introduction and Examples}.
+% TUGboat, 11(1), 69\figuredash85, 1990,
+% \biburl{http://www.tug.org/TUGboat/Articles/tb11-1/tb27salomon.pdf}.
+%
+% \bibitem{package:setspace}
+% \bibauthor{Tobin, Geoffrey,} and \bibauthor{Robin Fairbairns}.
+% \bibtitle{Package~\packagename{setspace}}.
+% 2011,
+% \biburl{https://ctan.org/pkg/setspace}.
+%
+% \bibitem{package:geometry}
+% \bibauthor{Umeki, Hideo}.
+% \bibtitle{Package~\packagename{geometry}}.
+% 2020,
+% \biburl{https://ctan.org/pkg/geometry}.
+%
+% \bibitem{wermuth:2016}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{Tracing paragraphs}.
+% TUGboat, 37(3), 358\figuredash373, 2016,
+% \biburl{https://tug.org/TUGboat/tb37-3/tb117wermuth.pdf}.
+%
+% \bibitem{wermuth:2017a}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{The optimal value for \cs{emergencystretch}}.
+% TUGboat, 38(1), 65\figuredash86, 2017,
+% \biburl{https://tug.org/TUGboat/tb38-1/tb118wermuth.pdf}.
+%
+% \bibitem{wermuth:2017c}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{A note on \cs{linepenalty}}.
+% TUGboat, 38(3), 400\figuredash414, 2017,
+% \biburl{https://tug.org/TUGboat/tb38-3/tb120wermuth.pdf}.
+%
+% \bibitem{wermuth:2018}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{Experiments with \cs{parfillskip}}.
+% TUGboat, 39(3), 276\figuredash303, 2018,
+% \biburl{https://tug.org/TUGboat/tb39-3/tb123wermuth-parfillskip.pdf}.
+%
+% \bibitem{wermuth:2020}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{An attempt at ragged-right typesetting}.
+% TUGboat, 41(1), 73\figuredash94, 2020,
+% \biburl{https://tug.org/TUGboat/tb41-1/tb127wermuth-ragged.pdf}.
+%
+% \bibitem{wermuth:2022-8-2}
+% \bibauthor{Wermuth, Udo}.
+% Personal communication.
+% August~2, 2022.
+%
+% \bibitem{wermuth:2023}
+% \bibauthor{Wermuth, Udo}.
+% \bibtitle{Vertical alignments in plain \TeX}.
+% TUGboat, 44(3), 427\figuredash440, 2023,
+% \biburl{https://tug.org/TUGboat/tb44-3/tb138wermuth-valign.pdf}.
+%
+% \bibitem{package:hyphenat}
+% \bibauthor{Wilson, Peter}.
+% \bibtitle{Package~\packagename{hyphenat}}.
+% 2004,
+% \biburl{https://ctan.org/pkg/hyphenat}.
+% The package is maintained by \bibauthor{W. Robertson}.
+%
+% \bibitem{wilson:2007}
+% \bibauthor{Wilson, Peter}.
+% \bibtitle{Glisterings}.
+% TUGboat, 28(2), 229\figuredash232, 2007,
+% \biburl{https://tug.org/TUGboat/tb28-2/tb89glister.pdf}.
+%
+% \bibitem{package:needspace}
+% \bibauthor{Wilson, Peter}.
+% \bibtitle{Package~\packagename{needspace}}.
+% 2010,
+% \biburl{https://ctan.org/pkg/needspace}.
+% The package is maintained by \bibauthor{W. Robertson}.
+% \end{thebibliography}
+% \end{RaggedRight}
+%
+% \sectionfinish
+% \clearpage
+% \begin{RaggedRight}
+% \setcounter{IndexColumns}{2}
+% \setlength{\columnsep}{30pt}
+% \label{sec:index}
+% \phantomsection
+% \addcontentsline{toc}{section}{Index}
+% \PrintIndex
+% \end{RaggedRight}
+% }
+%
+%
+% \sectionfinish
+% \clearpage
+% \appendix
+% \section{Package Code}\label{sec:package-code}
+% \addtocontents{toc}{\begingroup\small}
+% \addtocontents{toc}{\protect\begin{multicols}{2}}
+% \addtocontents{toc}{\protect\raggedcolumns}
+%
+% This is the \doublequotes{Reference Manual}~section of the documentation
+% where we describe the package's code
+% and explain its implementation details.
+%
+%
+% \begin{macrocode}
+%<*package>
+\NeedsTeXFormat{LaTeX2e}[2005/12/01]
+\ProvidesPackage{typog}
+ [2024/05/07 v0.3 TypoGraphic extensions]
+
+\RequirePackage{etoolbox}
+\RequirePackage{everyhook}
+\RequirePackage{xkeyval}
+
+% \end{macrocode}
+%
+% \bigskip
+%
+% \subsection*{Declarations of Lengths, Skips, etc.}
+%
+% \begin{macro}{\typog@TYPOG}
+% Define a macro that unequivocally identifies this very package.
+%
+% \begin{macrocode}
+\newcommand*{\typog@TYPOG}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typoglogo}
+% We have our own, low-key logo.
+%
+% \begin{macrocode}
+\newcommand*{\typoglogo}{\textsf{T\itcorr*{-5}\textsl{y}poG}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\iftypog@debug}
+% Our switch for debug information.
+%
+% \begin{macrocode}
+\newif\iftypog@debug
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@typeout}
+% Our debug information printer.
+%
+% \begin{macrocode}
+\newcommand*{\typog@typeout}[1]
+ {\iftypog@debug
+ \typeout{typog: #1}%
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@trim@spaces}
+% Pull \cs{tl\_trim\_spaces} into the \singlequotes{classic} namespace.
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\let\typog@trim@spaces=\tl_trim_spaces:o
+\ExplSyntaxOff
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@register@pdfsubstitute}
+% We often need to register (simple) substitute commands
+% suitable for \acronym{PDF}~bookmarks.
+% This is a convenient abbreviation for that task.
+%
+% \begin{macrocode}
+\newcommand{\typog@register@pdfsubstitute}[1]{%
+ \AtBeginDocument{%
+ \ifdefined\pdfstringdefDisableCommands
+ \pdfstringdefDisableCommands{#1}%
+ \fi}}
+
+% \end{macrocode}
+% \end{macro}
+%
+% Some functionality depends on package~\packagename{microtype}.
+% To complicate matters for certain setup operations, e.\,g., \cs{SetExpansion},
+% \packagename{microtype} must be loaded \emph{before} package~\packagename{typog},
+% a fact that we encode in \cs{iftypog@microtype@preloaded}.
+%
+% \begin{macro}{\iftypog@microtype@preloaded}
+% \begin{macrocode}
+\newif\iftypog@microtype@preloaded
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@require@preloaded@microtype}
+% It is easy to determine whether \packagename{microtype} has been sourced.
+% We raise to the occasion and define a pair of check macros
+% which simplify the test for the correct \packagename{microtype} load~state.
+%
+% \begin{macrocode}
+\ifdefined\MT@MT
+ \typog@typeout{package microtype preloaded}%
+ \typog@microtype@preloadedtrue
+ \def\typog@require@preloaded@microtype{\relax}
+\else
+ \typog@microtype@preloadedfalse
+ \def\typog@require@preloaded@microtype
+ {\PackageError{typog}%
+ {package microtype not (pre-)loaded}%
+ {package microtype must be loaded before package typog}}
+\fi
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\iftypog@microtype@loaded}
+% \begin{macrocode}
+\newif\iftypog@microtype@loaded
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@require@microtype}
+% This code duplicates \cs{typog@require@preloaded@microtype};
+% the only difference is that we call the test \emph{after} the preamble was processed.
+%
+% \begin{macrocode}
+\AtBeginDocument{
+ \ifdefined\MT@MT
+ \typog@typeout{package microtype loaded}%
+ \typog@microtype@loadedtrue
+ \def\typog@require@microtype{\relax}
+ \else
+ \typog@microtype@loadedfalse
+ \def\typog@require@microtype
+ {\PackageError{typog}%
+ {package microtype not loaded}%
+ {require package microtype before package typog}}%
+ \fi
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% Our own state\dots
+%
+% \begin{macro}{\typog@mathitalicscorrection}
+% \begin{macrocode}
+\newmuskip\typog@mathitalicscorrection
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@textitalicscorrection}
+% \begin{macrocode}
+\newlength{\typog@textitalicscorrection}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@ligaturekern}
+% \begin{macrocode}
+\newlength{\typog@ligaturekern}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raisecapitaldash}
+% \begin{macrocode}
+\newlength{\typog@raisecapitaldash}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raisecapitalguillemets}
+% \begin{macrocode}
+\newlength{\typog@raisecapitalguillemets}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raisecapitalhyphen}
+% \begin{macrocode}
+\newlength{\typog@raisecapitalhyphen}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raisecapitaltimes}
+% \begin{macrocode}
+\newlength{\typog@raisecapitaltimes}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raiseguillemets}
+% \begin{macrocode}
+\newlength{\typog@raiseguillemets}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@raisefiguredash}
+% \begin{macrocode}
+\newlength{\typog@raisefiguredash}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@slashkern}
+% \begin{macrocode}
+\newlength{\typog@slashkern}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@breakpenalty}
+% \begin{macrocode}
+\newcommand*{\typog@breakpenalty}{\exhyphenpenalty}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@dim@unit}
+% We would like to express the argument values
+% for example of \cs{kernedhyphen*} and \cs{kernedhyphen}
+% as multiples of a thousandth of an~em.
+% Therefore, we define a dimen as \doublequotes{base unit} which simplifies matters greatly.
+%
+% \begin{macrocode}
+\newlength{\typog@dim@unit}
+\setlength{\typog@dim@unit}{.001em}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@trackingttspacing}
+% \begin{macrocode}
+\newcommand*{\typog@trackingttspacing}{300, 90, 60}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@shrink@i}
+% The default configuration for shrink values.
+%
+% \begin{macrocode}
+\newcommand*{\typog@default@shrink@i}{5}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@shrink@ii}
+% \begin{macrocode}
+\newcommand*{\typog@default@shrink@ii}{10}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@shrink@iii}
+% \begin{macrocode}
+\newcommand*{\typog@default@shrink@iii}{20}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@shrink@i}
+% Configurable shrink values.
+% Initialized from the \code{typog@default@shrink@} set.
+%
+% \begin{macrocode}
+\newcommand*{\typog@shrink@i}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@shrink@ii}
+% \begin{macrocode}
+\newcommand*{\typog@shrink@ii}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@shrink@iii}
+% \begin{macrocode}
+\newcommand*{\typog@shrink@iii}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@stretch@i}
+% The default configuration for stretch values.
+%
+% \begin{macrocode}
+\newcommand*{\typog@default@stretch@i}{5}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@stretch@ii}
+% \begin{macrocode}
+\newcommand*{\typog@default@stretch@ii}{10}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@stretch@iii}
+% \begin{macrocode}
+\newcommand*{\typog@default@stretch@iii}{20}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@stretch@i}
+% Configurable stretch values.
+% Initialized from the \code{typog@default@stretch} set.
+%
+% \begin{macrocode}
+\newcommand*{\typog@stretch@i}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@stretch@ii}
+% \begin{macrocode}
+\newcommand*{\typog@stretch@ii}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@stretch@iii}
+% \begin{macrocode}
+\newcommand*{\typog@stretch@iii}{}
+% \end{macrocode}
+% \end{macro}
+%
+% \iffalse
+
+\def\typog@one@of@three#1,#2,#3\relax{\typog@trim@spaces{#1}}
+\def\typog@two@of@three#1,#2,#3\relax{\typog@trim@spaces{#2}}
+\def\typog@three@of@three#1,#2,#3\relax{\typog@trim@spaces{#3}}
+
+\newcommand*{\typog@triple@get@i}[1]{\expandafter\typog@one@of@three #1\relax}
+\newcommand*{\typog@triple@get@ii}[1]{\expandafter\typog@two@of@three #1\relax}
+\newcommand*{\typog@triple@get@iii}[1]{\expandafter\typog@three@of@three #1\relax}
+
+\newcommand*{\typog@set@shrink@limits}
+ {\edef\typog@@star{*}%
+ \edef\typog@@limit{\typog@triple@get@i{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@i{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@ii{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@ii{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@iii{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@iii{\number\typog@@limit}\fi}
+
+\newcommand*{\typog@set@stretch@limits}
+ {\edef\typog@@star{*}%
+ \edef\typog@@limit{\typog@triple@get@i{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@i{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@ii{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@ii{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@iii{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@iii{\number\typog@@limit}\fi}
+
+\DeclareOptionX<typog>{breakpenalty}%
+ {\renewcommand*{\typog@breakpenalty}{#1}}
+\DeclareOptionX<typog>{debug}{\typog@debugtrue}
+\DeclareOptionX<typog>{mathitalicscorrection}[.4mu]%
+ {\typog@mathitalicscorrection=#1\relax}%
+\DeclareOptionX<typog>{nodebug}{\typog@debugfalse}
+\DeclareOptionX<typog>{textitalicscorrection}[.02em]%
+ {\setlength{\typog@textitalicscorrection}{#1}}
+\DeclareOptionX<typog>{ligaturekern}[.033333em]%
+ {\setlength{\typog@ligaturekern}{#1}}
+\DeclareOptionX<typog>{raisecapitaldash}[\z@]%
+ {\setlength{\typog@raisecapitaldash}{#1}}
+\DeclareOptionX<typog>{raisecapitalguillemets}[\z@]%
+ {\setlength{\typog@raisecapitalguillemets}{#1}}
+\DeclareOptionX<typog>{raisecapitalhyphen}[\z@]%
+ {\setlength{\typog@raisecapitalhyphen}{#1}}
+\DeclareOptionX<typog>{raisecapitaltimes}[\z@]%
+ {\setlength{\typog@raisecapitaltimes}{#1}}
+\DeclareOptionX<typog>{raiseguillemets}[\z@]%
+ {\setlength{\typog@raiseguillemets}{#1}}
+\DeclareOptionX<typog>{raisefiguredash}[\z@]%
+ {\setlength{\typog@raisefiguredash}{#1}}
+\DeclareOptionX<typog>{raise*}[\z@]%
+ {\setlength{\typog@raisecapitaldash}{#1}%
+ \setlength{\typog@raisecapitalhyphen}{#1}%
+ \setlength{\typog@raisecapitaltimes}{#1}%
+ \setlength{\typog@raisefiguredash}{#1}}
+\DeclareOptionX<typog>{shrinklimits}%
+ [\typog@default@shrink@i, \typog@default@shrink@ii, \typog@default@shrink@iii]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `shrinklimits' can only be used in the preamble}%
+ \else
+ \edef\typog@shrinklimits{#1}%
+ \typog@set@shrink@limits
+ \fi}
+\DeclareOptionX<typog>{slashkern}[.05em]%
+ {\setlength{\typog@slashkern}{#1}}
+\DeclareOptionX<typog>{stretchlimits}%
+ [\typog@default@stretch@i, \typog@default@stretch@ii, \typog@default@stretch@iii]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `stretchlimits' can only be used in the preamble}%
+ \else
+ \edef\typog@stretchlimits{#1}%
+ \typog@set@stretch@limits
+ \fi}
+\DeclareOptionX<typog>{trackingttspacing}[\typog@trackingttspacing]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `trackingttspacing' can only be used in the preamble}%
+ \else
+ \typog@typeout{trackingttspacing=#1}%
+ \SetTracking[outer spacing={#1}]{encoding=*, family=tt*}{0}%
+ \fi}
+
+\newcommand*{\typog@initialize@options}
+ {\ExecuteOptionsX<typog>{
+ ligaturekern,
+ mathitalicscorrection, textitalicscorrection,
+ raisecapitaldash, raisecapitalhyphen, raisecapitaltimes,
+ raiseguillemets, raisecapitalguillemets,
+ raisefiguredash,
+ slashkern}
+ \ifdefined\MT@MT
+ \unless\ifx\@onlypreamble\@notprerr
+ \ExecuteOptionsX<typog>{shrinklimits, stretchlimits}
+ \fi
+ \fi}
+
+\typog@initialize@options
+\ProcessOptionsX<typog>
+
+% \fi
+%
+%
+% \subsection*{Setup}
+%
+% \begin{environment}{typogsetup}
+% An empty argument list resets all initialized values to their defaults.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{typogsetup}{m}
+ {\def\typog@@arg{#1}%
+ \ifx\typog@@arg\empty
+ \typog@initialize@options
+ \else
+ \setkeys{typog}{#1}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\typogget}
+% \begin{macrocode}
+\NewDocumentCommand{\typogget}{m}{\csname typog@#1\endcsname}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Information}
+%
+% \begin{macro}{\typog@round@dim@to@tenths}
+% \begin{macrocode}
+\ExplSyntaxOn
+\newcommand*{\typog@round@dim@to@tenths}[1]
+ {\fp_to_decimal:n {round(10 * \dim_to_fp:n{#1} / 1\p@) / 10}}
+\ExplSyntaxOff
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@formatsizeinfo}
+% Arguments 1 and~2 are the font size and the line spacing.
+% The third parameter adds (decorative) units to both numbers.
+%
+% \begin{macrocode}
+\newcommand*{\typog@formatsizeinfo}[3]
+ {#1#3\kernedslash #2#3}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fontsizeinfo}
+% All macros defined inside of \cs{fontsizeinfo} must be global
+% because the call can occur inside of a group.
+%
+% The two \cs{edef}s at the beginning capture the desired values
+% at the point where the macro \emph{is called}.
+% The user-macro is tricky for we need
+% a global macro with a constructed name
+% and an associated starred version.
+%
+% \begin{implementationnote}
+% \cs{@ifstar} caused too many problems which \cs{@ifnextchar} in combination with
+% \cs{@gobble} avoid.
+% \end{implementationnote}
+%
+% \begin{macrocode}
+\NewDocumentCommand{\fontsizeinfo}{s m}
+ {\global\expandafter\edef\csname typog@fontsize@#2\endcsname
+ {\typog@round@dim@to@tenths{\fontdimen6\font}}%
+ \global\expandafter\edef\csname typog@linespacing@#2\endcsname
+ {\typog@round@dim@to@tenths{\baselineskip}}%
+ \protected\expandafter\gdef\csname #2\endcsname
+ {\@ifnextchar*{\typog@formatsizeinfo
+ {\csname typog@fontsize@#2\endcsname}%
+ {\csname typog@linespacing@#2\endcsname}%
+ {}% no unit
+ \ignorespaces % eat spaces after star
+ \@gobble} % consume the star itself
+ {\typog@formatsizeinfo
+ {\csname typog@fontsize@#2\endcsname}%
+ {\csname typog@linespacing@#2\endcsname}%
+ {\,pt}% decorative unit `pt'
+ }}}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@default@inspect@id@prefix}
+% Id-prefix for those |typoinspect|~environments
+% that were not identified by the user.
+%
+% \begin{macrocode}
+\newcommand*{\typog@default@inspect@id@prefix}{a-}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{typog@inspect@count}
+% Counter to supply unique number and in turn \meta{id}
+% for those |typoinspect|~environments
+% that were not identified by the user.
+%
+% \begin{macrocode}
+\newcounter{typog@inspect@count}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{typoginspect}
+% \begin{macrocode}
+\define@key[typog]{typoginspect}{tracingboxes}[\maxdimen]%
+ {\def\typog@@typoginspect@tracingboxes{#1}}
+\NewDocumentEnvironment{typoginspect}{O{} m}
+ {\def\typog@@typoginspect@tracingboxes{\m@ne}%
+ \setkeys[typog]{typoginspect}{#1}%
+% \end{macrocode}
+%
+% If the user does not supply an \meta{id},
+% we fall back to out own counter
+% and construct a hopefully unique \meta{id} from that.
+%
+% \begin{macrocode}
+ \edef\typog@@arg{#2}%
+ \ifx\typog@@arg\empty
+ \stepcounter{typog@inspect@count}%
+ \edef\typog@@id{\typog@default@inspect@id@prefix\arabic{typog@inspect@count}}%
+ \else
+ \edef\typog@@id{\typog@trim@spaces{\typog@@arg}}%
+ \fi
+ \typeout{<typog-inspect id="\typog@@id" job="\jobname" line="\the\inputlineno" page="\the\value{page}">}%
+% \end{macrocode}
+%
+% Set both badness thresholds to absurdly low values as to activate \TeX's reports.
+%
+% \begin{macrocode}
+ \hbadness=\m@ne
+ \vbadness=\m@ne
+% \end{macrocode}
+%
+% Carefully select the tracing functionality we want (to improve our typography).
+% Too much trace data distracts
+% and the user always can turn on more tracing at the beginning of the environment.
+%
+% \begin{macrocode}
+ \tracingnone
+ \tracingpages=\@ne
+ \tracingparagraphs=\@ne
+ \showboxbreadth=\typog@@typoginspect@tracingboxes
+ \showboxdepth=\typog@@typoginspect@tracingboxes}
+ {\typeout{</typog-inspect>}%
+ \ignorespacesafterend}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{typoginspectpar}
+% Companion environment to |typoginspect|
+% which adds a \cs{par} before the end of the group.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{typoginspectpar}{m}
+ {\typoginspect{#1}}
+ {\par\endtypoginspect}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Hyphenation}
+%
+% \begin{macro}{\typog@allowhyphenation}
+% Re-enable automatic hyphenation.
+%
+% The same or almost the same implementation can be found
+% in \packagename{babel} as macro~\cs{bbl@allowhyphens}
+% and \packagename{hyphenat} as macro~\cs{prw@zbreak}.
+%
+% \begin{macrocode}
+\newcommand*{\typog@allowhyphenation}
+ {\ifvmode
+ \relax
+ \else
+ \nobreak
+ \hskip\z@skip
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\allowhyphenation}
+% Define a user-visible alias unless the name is already used.
+%
+% \begin{macrocode}
+\unless\ifdefined\allowhyphenation
+ \let\allowhyphenation=\typog@allowhyphenation
+\fi
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\breakpoint}
+% The starred form inhibits hyphenation of the right-hand component.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\breakpoint}{s}
+ {\discretionary{}{}{}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@allowhyphenation}}
+
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \def\breakpoint#1{\if*\detokenize{#1}\ignorespaces\fi}%
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{hyphenmin}
+% \changes{v0.3}{2024-05-04}{New environment.}
+% No trickery here. -- We use the mandatory argument for the value of \cs{lefthyphenmin} if
+% the optional argument has been omitted.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{hyphenmin}{o m}
+ {\lefthyphenmin=\IfNoValueTF{#1}{#2}{#1}%
+ \righthyphenmin=#2}
+ {}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Disable/Break Ligatures}
+%
+% \begin{macro}{\typog@hyphen}
+% We define our own hyphen so the user can override the definition in a pinch.
+%
+% \begin{macrocode}
+\newcommand*{\typog@hyphen}{\char`-}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\nolig}
+% \begin{macrocode}
+\NewDocumentCommand{\nolig}{s o}
+ {\dimen0=\IfNoValueTF{#2}{\typog@ligaturekern}{#2\typog@dim@unit}%
+ \IfBooleanTF{#1}%
+ {\kern\dimen0\ignorespaces}%
+ {\discretionary{\typog@hyphen}{}{\kern\dimen0}%
+ \typog@allowhyphenation
+ \IfNoValueF{#2}{\ignorespaces}}}
+
+% \end{macrocode}
+%
+% The \acronym{PDF}-ready version of \cs{nolig} cannot be implemented with \cs{futurelet}.
+% Doh!
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\nolig}{s o m}{%
+ \ifx\typog@TYPOG#3\typog@TYPOG
+ \relax
+ \else
+ \ifx\relax#3\relax
+ \relax
+ \else
+ \PackageError{typog}
+ {Missing third argument of \nolig}
+ {Append empty group or \relax after macro invocation}
+ \fi
+ \fi}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Manual Italic Correction}
+%
+% \begin{macro}{\typog@itcorr@text@unconditional}
+% Fallback italics correction for text mode.
+%
+% \begin{macrocode}
+\newcommand*{\typog@itcorr@text@unconditional}[1]
+ {\kern#1\typog@textitalicscorrection}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@itcorr@text}
+% Conditional italics correction depending on
+% the current font's own italics correction,
+% i.\,e., \cs{fontdimen1}.
+%
+% \begin{macrocode}
+\newcommand*{\typog@itcorr@text}[1]
+ {\def\typog@@strength{#1}%
+ \dimen0=\fontdimen1\font
+ \ifdim\dimen0=\z@
+ \typog@itcorr@text@unconditional{\typog@@strength}%
+ \else
+ \kern\typog@@strength\dimen0
+ \fi}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@itcorr@math}
+% Italics correction for math mode.
+%
+% \begin{macrocode}
+\newcommand*{\typog@itcorr@math}[1]
+ {\mkern#1\typog@mathitalicscorrection}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\itcorr}
+% If the font has no italics correction we fall back to out own length.
+% In text mode the starred version always uses the fallback.
+% The star is a no-op in math mode.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\itcorr}{s m}
+ {\ifmmode
+ \typog@itcorr@math{#2}%
+ \else
+ \IfBooleanTF{#1}%
+ {\typog@itcorr@text{#2}}%
+ {\typog@itcorr@text@unconditional{#2}}%
+ \fi}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\itcorr}{s m}{}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Apply Extra Kerning}
+%
+% \subsubsection*{Slash}
+%
+% \begin{macro}{\typog@forwardslash}
+% We define our own forward-slash so the user can override the definition in a pinch.
+%
+% \begin{macrocode}
+\newcommand*{\typog@forwardslash}{\char`/}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\kernedslash}
+% Macro~\cs{kernedslash} introduces a hyphenation possibility right after the dash,
+% whereas the starred version does not.
+%
+% By the way, \cs{slash} expands to `|/|\cs{penalty}\cs{exhyphenpenalty}'.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\kernedslash}{s}
+ {\hspace*{\typog@slashkern}%
+ \typog@forwardslash
+ \IfBooleanTF{#1}%
+ {\hspace*{\typog@slashkern}\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation\hspace*{\typog@slashkern}}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \def\kernedslash#1{\if*\detokenize{#1}/\ignorespaces\else/#1\fi}%
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection*{Hyphen}
+%
+% \begin{macro}{\kernedhyphen}
+% \begin{macrocode}
+\NewDocumentCommand{\kernedhyphen}{s O{0} m m}
+ {\ifmmode
+ \mspace{\muexpr(#3 mu) * 18 / 1000}%
+ \raisebox{#2\typog@dim@unit}{$\m@th\mathord{-}$}%
+ \mspace{\muexpr(#4 mu) * 18 / 1000}%
+ \else
+ \def\typog@@auto{*}%
+ \def\typog@@optarg{#2}%
+ \hspace*{#3\typog@dim@unit}%
+ \raisebox{\ifx\typog@@optarg\typog@@auto
+ \typog@raisecapitalhyphen
+ \else
+ \typog@@optarg\typog@dim@unit
+ \fi}{\typog@hyphen}%
+ \hspace{#4\typog@dim@unit}%
+ \IfBooleanT{#1}{\nobreak}%
+ \fi}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\kernedhyphen}{s o m m}{-}
+}
+% \end{macrocode}
+% \end{macro}
+%
+% One-argument shorthands.
+%
+% \begin{macro}{\leftkernedhyphen}
+% Apply kerning on the left-hand side of the hyphen only.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\leftkernedhyphen}{s O{0} m}
+ {\IfBooleanTF{#1}%
+ {\kernedhyphen*[#2]{#3}{0}\ignorespaces}%
+ {\kernedhyphen[#2]{#3}{0}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\leftkernedhyphen}{s o m}{-}
+}
+
+% \end{macrocode}
+%
+% \begin{macro}{\rightkernedhyphen}
+% Apply kerning on the right-hand side of the hyphen only.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\rightkernedhyphen}{s O{0} m}
+ {\IfBooleanTF{#1}%
+ {\kernedhyphen*[#2]{0}{#3}\ignorespaces}%
+ {\kernedhyphen[#2]{0}{#3}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\rightkernedhyphen}{s o m}{-}
+}
+
+% \end{macrocode}
+%
+%
+% \subsection{Raise Selected Characters}
+%
+% \begin{macro}{\typog@breakpoint}
+% We want our own penalty for a line-break at a particular point.
+% The predefined \cs{allowbreak} is too eager.
+% A package-private, user-configurable penalty fits best.
+%
+% \begin{macrocode}
+\newcommand*{\typog@breakpoint}
+ {\penalty\typog@breakpenalty}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\capitalhyphen}
+% Macro~\cs{capitalhyphen} introduces a hyphenation possibility right after the dash,
+% whereas the starred version does not.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\capitalhyphen}{s}
+ {\raisebox{\typog@raisecapitalhyphen}{\typog@hyphen}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+% \end{macrocode}
+%
+% The non-hyperref version's code is straightforward.
+% The \cs{pdfstringdefDisableCommands}~version must be expandable
+% and must match the other version's signature.
+% Yikes!
+% We exploit the fact that conditions are expandable.
+% However, we cannot use \cs{typog@hyphen} in the expansion as \cs{char} gets in the way.
+% So, we fall back to the least~common denominator and use a bare dash.
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \def\capitalhyphen#1{%
+ \if*\detokenize{#1}%
+ -\ignorespaces
+ \else
+ -#1%
+ \fi}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\capitalendash}
+% Macro~\cs{capitalendash} introduces a hyphenation possibility right after the dash;
+% its starred version does not.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\capitalendash}{s}
+ {\raisebox{\typog@raisecapitaldash}{\textendash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+\let\capitaldash=\capitalendash
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \def\capitalendash#1{%
+ \if*\detokenize{#1}%
+ \textendash\ignorespaces
+ \else
+ \textendash#1%
+ \fi}
+ \let\capitaldash=\capitalendash
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\capitalemdash}
+% Macro~\cs{capitalemdash} introduces a hyphenation possibility right after the dash;
+% its starred version does not.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\capitalemdash}{s}
+ {\raisebox{\typog@raisecapitaldash}{\textemdash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \def\capitalemdash#1{%
+ \if*\detokenize{#1}%
+ \textemdash\ignorespaces
+ \else
+ \textemdash#1%
+ \fi}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\figuredash}
+% Macro~\cs{figuredash} introduces a hyphenation possibility right after the dash;
+% its starred version does not.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\figuredash}{s}
+ {\raisebox{\typog@raisefiguredash}{\textendash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\figuredash=\capitaldash}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\capitaltimes}
+% \begin{macrocode}
+\NewDocumentCommand{\capitaltimes}{}
+ {\ifmmode
+ \mathbin{\raisebox{\typog@raisecapitaltimes}{$\m@th\times$}}%
+ \else
+ \raisebox{\typog@raisecapitaltimes}{\texttimes}%
+ \fi}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\capitaltimes}{}{\texttimes}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\singleguillemetleft}
+% \begin{macrocode}
+\NewDocumentCommand{\singleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raiseguillemets}{\guilsinglleft}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\singleguillemetleft\guilsinglleft}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\singleguillemetright}
+% \begin{macrocode}
+\NewDocumentCommand{\singleguillemetright}{}
+ {\raisebox{\typog@raiseguillemets}{\guilsinglright}%
+ \typog@allowhyphenation}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\singleguillemetright\guilsinglright}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\doubleguillemetleft}
+% \begin{macrocode}
+\NewDocumentCommand{\doubleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raiseguillemets}{\guillemotleft}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\doubleguillemetleft\guillemotleft}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\doubleguillemetright}
+% \begin{macrocode}
+\NewDocumentCommand{\doubleguillemetright}{}
+ {\raisebox{\typog@raiseguillemets}{\guillemotright}%
+ \typog@allowhyphenation}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\doubleguillemetright\guillemotright}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Singleguillemetleft}
+% \begin{macrocode}
+\NewDocumentCommand{\Singleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raisecapitalguillemets}{\guilsinglleft}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\Singleguillemetleft\guilsinglleft}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Singleguillemetright}
+% \begin{macrocode}
+\NewDocumentCommand{\Singleguillemetright}{}
+ {\raisebox{\typog@raisecapitalguillemets}{\guilsinglright}%
+ \typog@allowhyphenation}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\Singleguillemetright\guilsinglright}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Doubleguillemetleft}
+% \begin{macrocode}
+\NewDocumentCommand{\Doubleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raisecapitalguillemets}{\guillemotleft}}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\Doubleguillemetleft\guillemotleft}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\Doubleguillemetright}
+% \begin{macrocode}
+\NewDocumentCommand{\Doubleguillemetright}{}
+ {\raisebox{\typog@raisecapitalguillemets}{\guillemotright}%
+ \typog@allowhyphenation}
+% \end{macrocode}
+%
+% \acronym{PDF}-substitute definition
+%
+% \begin{macrocode}
+\typog@register@pdfsubstitute{\let\Doubleguillemetright\guillemotright}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection[Align Last Line]{Align Last Line of a Paragraph}
+%
+% The code of environment |lastlineraggedleftpar|
+% has been inspired by macro~\cs{lastlineraggedleft}~\cite[Sec.~2]{wilson:2007}.
+%
+% \begin{environment}{lastlineraggedleftpar}
+% \begin{macrocode}
+\NewDocumentEnvironment{lastlineraggedleftpar}{}
+ {\lastlinefit=0%
+ \setlength{\leftskip}{\z@ \@plus 1fil}%
+ \setlength{\rightskip}{-\leftskip}%
+ \setlength{\parfillskip}{\leftskip}}
+ {\par}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{lastlineflushrightpar}
+% Define |lastlineflushrightpar| as an alias of |lastlineraggedleftpar|.
+%
+% \begin{macrocode}
+\let\lastlineflushrightpar=\lastlineraggedleftpar
+\let\endlastlineflushrightpar=\endlastlineraggedleftpar
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{lastlinecenteredpar}
+% The code of environment |lastlinecenteredpar|
+% has been inspired by \textit{Tex By Topic}~\cite[Sec.~18.3.1]{eijkhout:2007}.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{lastlinecenteredpar}{}
+ {\lastlinefit=0%
+ \setlength{\leftskip}{\z@ \@plus .5fil}%
+ \setlength{\rightskip}{-\leftskip}%
+ \setlength{\parfillskip}{\z@ \@plus 1fil}}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection[Fill Last Line]
+% {Fill Last Line of a Paragraph}
+%
+% \begin{environment}{shortenpar}
+% \begin{macrocode}
+\NewDocumentEnvironment{shortenpar}{}
+ {\advance\looseness by -1
+ \ifnum\tracingparagraphs>0
+ \typeout{@ looseness \the\looseness}%
+ \fi}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{prolongpar}
+% We try to be prudent and inhibit hyphenation of the next-to-last line
+% just in case the longer paragraph could be cheaply achieved by hyphenation
+% --~at the worst~-- of the last word.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{prolongpar}{}
+ {\finalhyphendemerits=100000001
+ \advance\looseness by 1
+ \ifnum\tracingparagraphs>0
+ \typeout{@ looseness \the\looseness}%
+ \fi}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\typog@covernextindentpar@zero@parindent}
+% This auxiliary macro and the following one
+% are meant as an easy means to override the defaults
+% of the user-visible environment~|covernextindentpar|.
+%
+% \begin{macrocode}
+\newcommand*{\typog@covernextindentpar@zero@parindent}{2em}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@covernextindentpar@nonzero@parindent}
+% \begin{macrocode}
+\newcommand*{\typog@covernextindentpar@nonzero@parindent}{2\parindent}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{covernextindentpar}
+% \begin{macrocode}
+\NewDocumentEnvironment{covernextindentpar}{o}
+ {\IfNoValueTF{#1}
+ {\ifdim\parindent=\z@
+ \dimen0=\dimexpr\linewidth - \typog@covernextindentpar@zero@parindent
+ \else
+ \dimen0=\dimexpr\linewidth - \typog@covernextindentpar@nonzero@parindent
+ \fi}
+ {\dimen0=\dimexpr\linewidth - (#1)}%
+ \parfillskip=\dimen0 \@minus \dimen0
+ \relax}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\typog@openlastlinepar@zero@parindent}
+% These auxiliary macros are meant as a means to override the defaults
+% of the user-visible environment~|openlastlinepar|.
+%
+% \begin{macrocode}
+\newcommand*{\typog@openlastlinepar@zero@parindent}{2em}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@openlastlinepar@nonzero@parindent}
+% \begin{macrocode}
+\newcommand*{\typog@openlastlinepar@nonzero@parindent}{2\parindent}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{openlastlinepar}
+% Compare with the suggestion in Ref.~\citenum{wermuth:2018}.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{openlastlinepar}{o}
+ {\IfNoValueTF{#1}
+ {\ifdim\parindent=\z@
+ \skip0=\typog@openlastlinepar@zero@parindent
+ \@plus 1fil
+ \@minus \typog@openlastlinepar@zero@parindent
+ \else
+ \skip0=\typog@openlastlinepar@nonzero@parindent
+ \@plus 1fil
+ \@minus \typog@openlastlinepar@nonzero@parindent
+ \fi}
+ {\dimen0=\dimexpr#1\relax
+ \skip0=\dimen0 \@plus 1fil \@minus \dimen0}
+ \parfillskip=\skip0}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Spacing}
+%
+% \begin{macro}{\widespacestrength}
+% Weight factor (``strength'') for \cs{fontdimen7}, the extra width of a sentence-ending
+% space, we apply to construct our \cs{widespace} if \(\cs{fontdimen7} \not= 0\). Can be
+% increased to get a more pronounced effect.
+%
+% \begin{macrocode}
+\newcommand*{\widespacestrength}{1.}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\widespacescale}
+% Scale factor we apply to the glue of the normal space to setup the glue of our
+% \cs{widespacescale}. Also used in the fall-back calculation for the width if
+% \(\cs{fontdimen7} = 0\).
+%
+% \begin{macrocode}
+\newcommand*{\widespacescale}{1.125}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\widespace}
+% \changes{v0.2}{2024-3-29}{Add fallback if \cs{fontdimen7} is zero. Extend with a starred version.}
+% \begin{macrocode}
+\NewDocumentCommand{\widespace}{s}
+ {\IfBooleanTF{#1}%
+ {\dimen0=\widespacescale\fontdimen2\font}%
+ {\ifdim\fontdimen7\font=\z@
+ \dimen0=\widespacescale\fontdimen2\font
+ \else
+ \dimen0=\dimexpr\fontdimen2\font +
+ \widespacestrength\fontdimen7\font
+ \fi}%
+ \hskip \glueexpr\dimen0
+ \@plus \widespacescale\fontdimen3\font
+ \@minus \widespacescale\fontdimen4\font
+ \ignorespaces}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\narrowspacestrength}
+% Weight factor (``strength'') for \cs{fontdimen7}, the extra width of a sentence-ending
+% space, we apply to construct our \cs{narrowspace} if \(\cs{fontdimen7} \not= 0\). Can be
+% increased to get a more pronounced effect.
+%
+% \begin{macrocode}
+\newcommand*{\narrowspacestrength}{.5}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\narrowspacescale}
+% Scale factor we apply to the glue of the normal space to setup the glue of our
+% \cs{narrowspacescale}. Also used in the fall-back calculation for the width if
+% \(\cs{fontdimen7} = 0\).
+%
+% \begin{macrocode}
+\newcommand*{\narrowspacescale}{.9375}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\narrowspace}
+% \changes{v0.2}{2024-3-29}{New macro.}
+% \begin{macrocode}
+\NewDocumentCommand{\narrowspace}{s}
+ {\IfBooleanTF{#1}%
+ {\dimen0=\narrowspacescale\fontdimen2\font}%
+ {\ifdim\fontdimen7\font=\z@
+ \dimen0=\narrowspacescale\fontdimen2\font
+ \else
+ \dimen0=\dimexpr\fontdimen2\font -
+ \narrowspacestrength\fontdimen7\font
+ \fi}%
+ \hskip \glueexpr\dimen0
+ \@plus \narrowspacescale\fontdimen3\font
+ \@minus \narrowspacescale\fontdimen4\font
+ \ignorespaces}
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% See also: TeX by Topic \cite[ch.~20, p.~185\figuredash190]{eijkhout:2007}.
+%
+% \begin{environment}{loosespacing}
+% \begin{macrocode}
+\NewDocumentEnvironment{loosespacing}{O{1}}
+ {\dimen2=\fontdimen2\font
+ \ifcase #1
+ \spaceskip=\z@
+ \or % 1 +5%
+ \spaceskip=1.05\dimen2 \@plus .5\dimen2 \@minus .1\dimen2
+ \or % 2 +10%
+ \spaceskip=1.1\dimen2 \@plus .5\dimen2 \@minus .1\dimen2
+ \or % 3 +20%
+ \spaceskip=1.2\dimen2 \@plus .6\dimen2 \@minus .2\dimen2
+ \else % >= 4 +30%
+ \spaceskip=1.3\dimen2 \@plus .8\dimen2 \@minus .3\dimen2
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{tightspacing}
+% \begin{macrocode}
+\NewDocumentEnvironment{tightspacing}{O{1}}
+ {\dimen2=\fontdimen2\font
+ \ifcase #1
+ \spaceskip=\z@
+ \or % 1 -1.25%
+ \spaceskip=.9875\dimen2 \@plus .0125\dimen2 \@minus .5\dimen2
+ \or % 2 -2.5%
+ \spaceskip=.975\dimen2 \@plus .025\dimen2 \@minus .5\dimen2
+ \or % 3 -5%
+ \spaceskip=.95\dimen2 \@plus .05\dimen2 \@minus .5\dimen2
+ \else % >= 4 -10%
+ \spaceskip=.9\dimen2 \@plus .1\dimen2 \@minus .5\dimen2
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Microtype Front\capitalhyphen End}
+%
+% \subsubsection*{Tracking}
+%
+% \begin{environment}{setfonttracking}
+%
+% To archieve the control we want,
+% we must tinker with \packagename{microtype's} internals.
+% Doh!
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{setfonttracking}{m}
+ {\edef\MT@letterspace@{#1}%
+ \lsstyle
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsubsection*{Font Expansion}
+%
+% \begin{macro}{\typog@setup@font@expansion}
+% Note that we cannot factor the encodings into a macro;
+% a single encoding would qualify, though.
+% We need to support multiple encodings and thus go with the literal solution.
+%
+% \begin{macrocode}
+\newcommand*{\typog@setup@font@expansion}
+ {\SetExpansion
+ [context = typog@shrink1,
+ shrink = \typog@shrink@i,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@shrink2,
+ shrink = \typog@shrink@ii,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@shrink3,
+ shrink = \typog@shrink@iii,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+
+ \SetExpansion
+ [context = typog@stretch1,
+ shrink = 0,
+ stretch = \typog@stretch@i]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@stretch2,
+ shrink = 0,
+ stretch = \typog@stretch@ii]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@stretch3,
+ shrink = 0,
+ stretch = \typog@stretch@iii]%
+ {encoding = {*}}%
+ {}
+
+ \SetExpansion
+ [context = typog@expand1,
+ shrink = \typog@shrink@i,
+ stretch = \typog@stretch@i]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@expand2,
+ shrink = \typog@shrink@ii,
+ stretch = \typog@stretch@ii]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@expand3,
+ shrink = \typog@shrink@iii,
+ stretch = \typog@stretch@iii]%
+ {encoding = {*}}%
+ {}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@test@microtype@expansion@feature}
+% We cannot even parse the \cs{iftypog@microtype@preloaded}~part further down
+% unless the \cs{ifMT@expansion}~conditional exists.
+% So we hoist this test in a macro of its own.
+% It only gets called if package~\packagename{microtype} already has been sourced.
+%
+% \begin{macrocode}
+\newcommand*{\typog@test@microtype@expansion@feature}
+ {\ifMT@expansion
+ \typog@typeout{microtype preloaded -- font expansion features available}%
+ \def\typog@require@microtype@expansion{\relax}
+ \typog@setup@font@expansion
+ \else
+ \PackageWarning{typog}{microtype preloaded,\space
+ but font expansion is disabled}%
+ \def\typog@require@microtype@expansion
+ {\PackageError{typog}
+ {microtype font expansion disabled}
+ {pass option `expansion' to package microtype}}
+ \fi}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@require@microtype@expansion}
+% We are all set for the initialization of the font expansion,
+% however, we must be careful in which (load-)state
+% package~\packagename{microtype} is in.
+% Compare the code for \cs{typog@require@microtype}
+% and~\cs{typog@require@preloaded@microtype}.
+%
+% Initialize our own flag and setup meaningful messages for later feature checks.
+%
+% \begin{macrocode}
+\iftypog@microtype@preloaded
+ \typog@test@microtype@expansion@feature
+\else
+ \def\typog@require@microtype@expansion
+ {\PackageError{typog}%
+ {package microtype not (pre-)loaded, %
+ which is required for typog's font expansion}%
+ {require package microtype before package typog}}
+\fi
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{setfontshrink}
+% \begin{macrocode}
+\NewDocumentEnvironment{setfontshrink}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@shrink1}%
+ \or % 2
+ \microtypecontext{expansion=typog@shrink2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@shrink3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{setfontstretch}
+% \begin{macrocode}
+\NewDocumentEnvironment{setfontstretch}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@stretch1}%
+ \or % 2
+ \microtypecontext{expansion=typog@stretch2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@stretch3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{setfontexpand}
+% \begin{macrocode}
+\NewDocumentEnvironment{setfontexpand}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@expand1}%
+ \or % 2
+ \microtypecontext{expansion=typog@expand2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@expand3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{nofontexpansion}
+% Implementation: We proceed a different approach with respect to requiring package microtype.
+% The semantics of the macro is to switch something off.
+% If it is not \singlequotes{on} because the necessary package was not loaded, a no-op is ok.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{nofontexpansion}{}
+ {\ifdefined\microtypesetup
+ \microtypesetup{expansion=false}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{nofontexpand}
+% Define |nofontexpand| as an alias of |nofontexpansion|.
+%
+% \begin{macrocode}
+\let\nofontexpand=\nofontexpansion
+\let\endnofontexpand=\endnofontexpansion
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsubsection*{Character Protrusion}
+%
+% \begin{environment}{nocharprotrusion}
+% See \singlequotes{Implementation} comment of |nofontexpansion|.
+%
+% \begin{macrocode}
+\NewDocumentEnvironment{nocharprotrusion}{}
+ {\ifdefined\microtypesetup
+ \microtypesetup{protrusion=false}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Sloppy Paragraphs}
+%
+% \begin{macro}{\typog@scaled@emergencystretch}
+% Compute the correct scale factor for the emergency stretch
+% even if we do not have a valid \cs{linewidth}.
+%
+% \begin{macrocode}
+\newcommand*{\typog@scaled@emergencystretch}[1]
+ {\emergencystretch=\ifdim\linewidth=\z@
+ #1%
+ \else
+ \dimexpr (#1) * \linewidth / \textwidth
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\slightlysloppy}
+% Macro~\cs{slightlysloppy} takes an optional~\meta{sloppiness} index ranging from~0 to~8,
+% where~0 means the same as \cs{fussy} and~8 or more works like \cs{sloppy}.
+% The default \meta{sloppiness} is~1.
+%
+% \begin{macrocode}
+\NewDocumentCommand{\slightlysloppy}{O{1}}
+ {\ifcase #1% 0
+ % \tolerance=200
+ % \emergencystretch=\z@
+ % \hfuzz=.1\p@
+ % \vfuzz=\hfuzz
+ \fussy
+ \or % 1
+ \pretolerance=165%
+ \tolerance=330%
+ \typog@scaled@emergencystretch{.375em}%
+ \hfuzz=.15\p@
+ \vfuzz=\hfuzz
+ \or % 2
+ \pretolerance=265%
+ \tolerance=530%
+ \typog@scaled@emergencystretch{.75em}%
+ \hfuzz=.15\p@
+ \vfuzz=\hfuzz
+ \or % 3
+ \pretolerance=435%
+ \tolerance=870%
+ \typog@scaled@emergencystretch{1.125em}%
+ \hfuzz=.2\p@
+ \vfuzz=\hfuzz
+ \or % 4
+ \pretolerance=705%
+ \tolerance=1410%
+ \typog@scaled@emergencystretch{1.5em}%
+ \hfuzz=.3\p@
+ \vfuzz=\hfuzz
+ \or % 5
+ \pretolerance=1155%
+ \tolerance=2310%
+ \typog@scaled@emergencystretch{1.875em}%
+ \hfuzz=.35\p@
+ \vfuzz=\hfuzz
+ \or % 6
+ \pretolerance=1880%
+ \tolerance=3760%
+ \typog@scaled@emergencystretch{2.25em}%
+ \hfuzz=.4\p@
+ \vfuzz=\hfuzz
+ \or % 7
+ \pretolerance=3065%
+ \tolerance=6130%
+ \typog@scaled@emergencystretch{2.625em}%
+ \hfuzz=.45\p@
+ \vfuzz=\hfuzz
+ \else % >= 8
+ % \tolerance=9999
+ % \emergencystretch=3em
+ % \hfuzz=.5\p@
+ % \vfuzz=\hfuzz
+ \sloppy
+ \fi
+ \ignorespaces}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{implementationnote}
+% \begin{itemize}
+% \item The \cs{tolerance}~values are calculated as the geometric mean of the extreme
+% values~200 and~9999. This means the factor
+% \begin{equation*}
+% f = \Big(\frac{9999}{200}\Big)^{1/8} \approx 1.63
+% \end{equation*}
+% defines additional tolerances which we generously round values in the actual
+% implementation.
+%
+% \item The \cs{emergencystretch} is scaled linearly with \meta{sloppiness} \emph{and} the
+% ratio of the actual \cs{linewidth} to the (maximum) \cs{textwidth}.
+%
+% \item The \cs{hfuzz}~values are interpolated linearly with \meta{sloppiness} between .1pt
+% and~.5pt.
+% \end{itemize}
+%
+% Maxima code to calculate the intermediate values.
+%
+% \begin{description}
+% \item[Initialize.] \code{load("list\_functions")\$}
+% \item[\cs{tolerance}:] \code{logspace(log10(200), log10(9999), 9), numer;}
+% \item[\cs{emergencystretch}:] \code{linspace(0, 3, 9), numer;}
+% \item[\cs{hfuzz}:] \code{linspace(0.1, 0.5, 9);}
+% \end{description}
+% \end{implementationnote}
+%
+% \begin{environment}{slightlysloppypar}
+% \begin{macrocode}
+\NewDocumentEnvironment{slightlysloppypar}{O{1}}
+ {\par\slightlysloppy[#1]\ignorespaces}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection[Vert.~Tie Paragraphs]{Vertically Partially-Tied Paragraphs}
+%
+% \begin{macro}{\typog@geometric@mean}
+% This is just the usual geometric mean of two values~\(x\) and~\(y\): \(\sqrt{x y}\).
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\newcommand*{\typog@geometric@mean}[2]
+ {\fp_to_int:n {sqrt((#1) * (#2))}}
+\ExplSyntaxOff
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{typog@mean@penalty}
+% Reserve a private counter for the geometric-mean penalties.
+%
+% \begin{macrocode}
+\newcounter{typog@mean@penalty}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\vtietop}
+% \begin{macrocode}
+\NewDocumentCommand{\vtietop}{O{3}}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\clubpenalty}}%
+ \typog@typeout{vtietop: penalties \the\@M--\the\value{typog@mean@penalty}--\the\clubpenalty}%
+ \unless\ifnum\clubpenalty<\@M
+ \PackageWarning{typog}{vtietop: clubpenalty=\the\clubpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \clubpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 3
+ \clubpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 4
+ \clubpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 5
+ \clubpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 6
+ \clubpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 7
+ \clubpenalties 8
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 8
+ \clubpenalties 9
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \else % >= 9
+ \clubpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{vtietoppar}
+% \begin{macrocode}
+\NewDocumentEnvironment{vtietoppar}{O{3}}
+ {\vtietop[#1]}
+ {\par
+ \ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\splicevtietop}
+% \begin{macrocode}
+\NewDocumentCommand{\splicevtietop}{O{3}}
+ {\let\typog@old@item=\@item
+ \def\@item[##1]{\typog@old@item[##1]\vtietop[#1]}%
+ \ignorespaces}
+
+% \end{macrocode}
+%
+% We define an extra style for the users of \packagename{enumitem}.
+% Its only drawback is that it hard-codes the default number of tied lines~(3).
+%
+% \begin{macrocode}
+\ifdefined\SetEnumitemKey
+ \SetEnumitemKey{vtietop}{first=\splicevtietop}
+\fi
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\vtiebot}
+% \begin{macrocode}
+\NewDocumentCommand{\vtiebot}{O{3}}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\widowpenalty}}%
+ \typog@typeout{vtiebot: penalties \the\@M--\the\value{typog@mean@penalty}--\the\widowpenalty}%
+ \unless\ifnum\widowpenalty<\@M
+ \PackageWarning{typog}{vtiebot: widowpenalty=\the\widowpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \widowpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 3
+ \widowpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 4
+ \widowpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 5
+ \widowpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 6
+ \widowpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 7
+ \widowpenalties 8
+ \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 8
+ \widowpenalties 9
+ \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \else % >= 9
+ \widowpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{vtiebotpar}
+% \begin{macrocode}
+\NewDocumentEnvironment{vtiebotpar}{O{3}}
+ {\vtiebot[#1]}
+ {\par
+ \ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\typog@vtiebotdisp}
+% \begin{macrocode}
+\NewDocumentCommand{\typog@vtiebotdisp}{m}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\displaywidowpenalty}}%
+ \typog@typeout{vtiebotdisp: penalties \the\@M--\the\value{typog@mean@penalty}--\the\displaywidowpenalty}%
+ \unless\ifnum\displaywidowpenalty<\@M
+ \PackageWarning{typog}{vtiebotdisp: displaywidowpenalty=\the\displaywidowpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \displaywidowpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 3
+ \displaywidowpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 4
+ \displaywidowpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 5
+ \displaywidowpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 6
+ \displaywidowpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 7
+ \displaywidowpenalties 8
+ \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 8
+ \displaywidowpenalties 9
+ \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \else % >= 9
+ \displaywidowpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \fi}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{vtiebotdisp}
+% \begin{macrocode}
+\NewDocumentEnvironment{vtiebotdisp}{O{3}}
+ {\typog@vtiebotdisp{#1}}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{vtiebotdisptoppar}
+% \begin{macrocode}
+\NewDocumentEnvironment{vtiebotdisptoppar}{O{3}o}
+ {\postdisplaypenalty=\@M
+ \predisplaypenalty=10001% in accordance with package `widows-and-orphans'
+ \edef\typog@@top@lines{\IfNoValueTF{#2}{#1}{#2}}%
+ \edef\typog@@after@display@math{\vtietop[\typog@@top@lines]}%
+ \PushPostHook{display}{\aftergroup\typog@@after@display@math}%
+ \vtiebotdisp[#1]}
+ {\par
+ \PopPostHook{display}%
+ \ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Breakable Disp.~Eqs.}
+%
+% \begin{environment}{breakabledisplay}
+% We use a different default, 3, than \cs{allowdisplaybreaks} which utilizes~4 as its
+% default.
+%
+% \begin{macrocode}
+\newenvironment*{breakabledisplay}[1][3]
+ {\allowdisplaybreaks[#1]}
+ {\ignorespacesafterend}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \subsection{Setspace Front-End}
+%
+% \begin{macro}{\typog@iter@limit}
+% The maximum number of iterations we perform before bailing out with an error. Can be
+% changed by the user if convergence is slow.
+%
+% \begin{macrocode}
+\newcommand*{\typog@setbaselineskip@iter@limit}{10}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@setbaselineskip@relative@error}
+% The maximum relative error of the ratio we tolerate for the final baselineskip over the
+% target baselineskip. Can also be changed by the user if necessary.
+%
+% \begin{macrocode}
+\newcommand*{\typog@setbaselineskip@relative@error}{.001}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@setbaselineskip}
+% Given the \meta{target-baselineskip} as argument iterate setting \cs{setstretch} until the
+% error drops below our threshold.
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new:Npn \typog@setbaselineskip #1
+{
+% \end{macrocode}
+%
+% Initialize our ``emergency-stop'' loop counter.
+%
+% \begin{macrocode}
+ \int_set:Nn \l_tmpa_int {1}
+ \int_set:Nn \l_tmpb_int {\typog@setbaselineskip@iter@limit}
+% \end{macrocode}
+%
+% Note that the call to \cs{glueexpr} is required to consume dimensions that carry
+% stretchability via |plus| or |minus|.
+%
+% \begin{macrocode}
+ \dim_set:Nn \l_tmpa_dim {\glueexpr #1}
+
+ \typog@typeout{\string\setbaselineskip:\space
+ initial\space baselineskip:\space \the\baselineskip}
+ \typog@typeout{\string\setbaselineskip:\space
+ target\space baselineskip:\space \dim_use:N \l_tmpa_dim}
+
+ \dim_compare:nNnTF {\baselineskip} > {\c_zero_dim}
+ {}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space
+ baselineskip\space not\space positive}
+ {}
+ }
+
+ \dim_compare:nNnTF {\l_tmpa_dim} > {\c_zero_dim}
+ {}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space target\space
+ baselineskip\space must\space be\space
+ positive}
+ {}
+ }
+
+ \skip_if_eq:nnTF {\l_tmpa_dim} {\glueexpr #1}
+ {}
+ {
+ \PackageWarning{typog}
+ {\string\setbaselineskip:\space argument\space
+ is\space a\space skip;\space
+ will\space ignore\space glue}
+ {}
+ }
+
+ \fp_set:Nn \l_tmpa_fp {\l_tmpa_dim / \baselineskip}
+ \fp_until_do:nNnn {abs(\l_tmpa_dim / \baselineskip - 1)} <
+ {\typog@setbaselineskip@relative@error}
+ {
+ \setstretch{\fp_use:N \l_tmpa_fp}
+ \fp_set:Nn \l_tmpa_fp
+ {\l_tmpa_fp * \l_tmpa_dim / \baselineskip}
+
+ \int_incr:N \l_tmpa_int
+ \int_compare:nNnTF {\l_tmpa_int} > {\l_tmpb_int}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space excessive\space
+ number\space of\space iterations:\space
+ \int_use:N \l_tmpa_int\space >\space
+ \int_use:N \l_tmpb_int}
+ {}
+ }
+ {}
+ }
+
+ \typog@typeout{\string\setbaselineskip:\space
+ final\space \string\setstretch\space argument:\space
+ \fp_use:N \l_tmpa_fp}
+ \typog@typeout{\string\setbaselineskip:\space
+ final\space baselineskip:\space \the\baselineskip}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\setbaselineskip}
+% \changes{v0.3}{2024-04-04}{New macro.}
+%
+% Set the \cs{baselineskip} to an absolute length.
+%
+% \begin{implementationnote}
+% Viewed as a standalone macro \cs{setbaselineskip} does not need the decoration
+% \cs{AfterPreamble}. However, all of its siblings, \cs{setbaselineskippercentage},
+% \cs{setleading}, and \cs{setleadingpercentage} then would behave differently as they are
+% delayed to the end of the preamble, but \cs{setbaselineskip} immediately becomes
+% effective. For example, the successive calls
+%
+% \begin{codeexample}
+% \cs{setbaselineskippercentage}\{140\} \\
+% \cs{setbaselineskip}\{12.5pt\}
+% \end{codeexample}
+%
+% \noindent
+% in the preamble would set the baselineskip to 140\% in the document. Therefore,
+% \cs{setbaselineskip} is delayed too and the order of the calls thus preserved.
+% \end{implementationnote}
+%
+% \begin{macrocode}
+\cs_new:Npn \setbaselineskip #1
+{
+ \AfterPreamble{\typog@setbaselineskip{#1}}
+ \ignorespaces
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\resetbaselineskip}
+% \changes{v0.3}{2024-04-04}{New macro.}
+%
+% Set the \cs{baselineskip} to \singlequotes{neutral}.
+%
+% \begin{macrocode}
+\cs_new:Npn \resetbaselineskip
+{
+ \AfterPreamble{\setstretch{1}}
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{ldimen}{\typogfontsize}
+% \changes{v0.3}{2024-04-04}{New dimen.}
+% Define the default font-size/quad size.
+%
+% \begin{macrocode}
+\dim_new:N \typogfontsize
+% \end{macrocode}
+%
+% Initialize \cs{typogfontsize} at the end of the preamble, which is after all fonts have
+% been setup.
+%
+% \begin{macrocode}
+\AfterEndPreamble{
+ \dim_set:Nn \typogfontsize {\fontdimen6\font}
+ \typog@typeout{\string\typogfontsize =
+ \dim_use:N \typogfontsize\space
+ (at\space begin\space of\space document)}
+}
+
+% \end{macrocode}
+% \end{ldimen}
+%
+% \begin{macro}{\setbaselineskippercentage}
+% \changes{v0.3}{2024-04-04}{New macro.}
+% \begin{macrocode}
+\cs_new:Npn \setbaselineskippercentage #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{
+ \fp_eval:n {(#1) / 100} \typogfontsize}
+ }
+ {
+ \PackageError{typog}
+ {\string\setbaselineskippercentage:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\setleading}
+% \changes{v0.3}{2024-04-04}{New macro.}
+% \begin{macrocode}
+\cs_new:Npn \setleading #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{\typogfontsize + \dimexpr #1}
+ }
+ {
+ \PackageError{typog}
+ {\string\setleading:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\setleadingpercentage}
+% \changes{v0.3}{2024-04-04}{New macro.}
+% \begin{macrocode}
+\cs_new:Npn \setleadingpercentage #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{
+ \fp_eval:n {1 + (#1) / 100} \typogfontsize}
+ }
+ {
+ \PackageError{typog}
+ {\string\setleadingpercentage:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+\ExplSyntaxOff
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Smooth Ragged}
+%
+% \begin{macro}{\typog@repeat}
+% As we shall have to repeat the line specifications for our paragraphs so often we introduce
+% the two argument macro~\cs{typog@repeat} that takes a \meta{repeat-count} and a \meta{body}
+% that is repeated.
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new_eq:NN \typog@repeat \prg_replicate:nn
+
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\typog@mod}
+% For error checking we shall need the modulo operation on integers, i.\,e., the remainder of
+% an integral division.
+%
+% \begin{macrocode}
+\newcommand*{\typog@mod}[2]{\int_mod:nn{#1}{#2}}
+\ExplSyntaxOff
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\typog@triplet@max@lines}
+% Maximum number of lines a smoothraggedright paragraph can have with the triplet generator.
+% The number must be divisible by~3.
+%
+% \begin{macrocode}
+\newcommand*{\typog@triplet@max@lines}{99}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{smoothraggedrightshapetriplet}
+% Engine for 3-line repetitions.
+%
+% \begin{macrocode}
+\define@key[typog]{smoothraggedrightshapetriplet}{leftskip}%
+ {\def\typog@@triplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapetriplet}{parindent}%
+ {\def\typog@@triplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapetriplet}{O{} m m m}
+ {\def\typog@@triplet@leftskip{\z@}%
+ \def\typog@@triplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapetriplet}{#1}%
+ \skip0=\typog@@triplet@leftskip\relax
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \typog@typeout{smoothraggedrightshapetriplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip3=\the\skip3}%
+ \unless\ifnum\typog@mod{\typog@triplet@max@lines}{3}=0
+ \PackageError{typog}
+ {Line number of triplet generator %
+ (\typog@triplet@max@lines) not divisible by 3}
+ {}
+ \fi
+ \edef\typog@@triplet@linespecs{%
+ \glueexpr \skip0 + \typog@@triplet@parindent\relax
+ \glueexpr \skip1 - \typog@@triplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3
+ \typog@repeat{\numexpr\typog@triplet@max@lines / 3 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3}}
+ \parshape=\typog@triplet@max@lines\typog@@triplet@linespecs\relax}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \begin{macro}{\typog@quintuplet@max@lines}
+% Maximum number of lines a smoothraggedright paragraph can have with the quintuplet
+% generator. The number must be divisible by~5.
+%
+% \begin{macrocode}
+\newcommand*{\typog@quintuplet@max@lines}{95}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{smoothraggedrightshapequintuplet}
+% Engine for 5-line repetitions.
+%
+% \begin{macrocode}
+\define@key[typog]{smoothraggedrightshapequintuplet}{leftskip}
+ {\def\typog@@quintuplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapequintuplet}{parindent}
+ {\def\typog@@quintuplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapequintuplet}{O{} m m m m m}
+ {\def\typog@@quintuplet@leftskip{\z@}%
+ \def\typog@@quintuplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapequintuplet}{#1}%
+ \skip0=\typog@@quintuplet@leftskip
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \skip4=#5\relax
+ \skip5=#6\relax
+ \typog@typeout{smoothraggedrightshapequintuplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip3=\the\skip3}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip4=\the\skip4}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip5=\the\skip5}%
+ \unless\ifnum\typog@mod{\typog@quintuplet@max@lines}{5}=0
+ \PackageError{typog}
+ {Line number of quintuplet generator %
+ (\typog@quintuplet@max@lines) not divisible by 5}
+ {}
+ \fi
+ \edef\typog@@quintuplet@linespecs{%
+ \glueexpr \skip0 + \typog@@quintuplet@parindent\relax
+ \glueexpr \skip1 - \typog@@quintuplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5
+ \typog@repeat{\numexpr\typog@quintuplet@max@lines / 5 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5}}
+ \parshape=\typog@quintuplet@max@lines\typog@@quintuplet@linespecs\relax}
+ {\par}
+% \end{macrocode}
+
+% \end{environment}
+%
+%
+% \begin{macro}{\typog@septuplet@max@lines}
+% Maximum number of lines a smoothraggedright paragraph can have with the septuplet
+% generator. The number must be divisible by~7.
+%
+% \begin{macrocode}
+\newcommand*{\typog@septuplet@max@lines}{98}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{smoothraggedrightshapeseptuplet}
+% Engine for 7-line repetitions.
+%
+% \begin{macrocode}
+\define@key[typog]{smoothraggedrightshapeseptuplet}{leftskip}%
+ {\def\typog@@septuplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapeseptuplet}{parindent}%
+ {\def\typog@@septuplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapeseptuplet}{O{} m m m m m m m}
+ {\def\typog@@septuplet@leftskip{\z@}%
+ \def\typog@@septuplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapeseptuplet}{#1}%
+ \skip0=\typog@@septuplet@leftskip
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \skip4=#5\relax
+ \skip5=#6\relax
+ \skip6=#7\relax
+ \skip7=#8\relax
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip3=\the\skip3}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip4=\the\skip4}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip5=\the\skip5}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip6=\the\skip6}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip7=\the\skip7}%
+ \unless\ifnum\typog@mod{\typog@septuplet@max@lines}{7}=0
+ \PackageError{typog}
+ {Line number of septuplet generator %
+ (\typog@septuplet@max@lines) not divisible by 7}
+ {}
+ \fi
+ \edef\typog@@septuplet@linespecs{%
+ \glueexpr \skip0 + \typog@@septuplet@parindent\relax
+ \glueexpr \skip1 - typog@@septuplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5 \skip0 \skip6 \skip0 \skip7
+ \typog@repeat{\numexpr\typog@septuplet@max@lines / 7 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5 \skip0 \skip6 \skip0 \skip7}}
+ \parshape=\typog@septuplet@max@lines\typog@@septuplet@linespecs\relax}
+ {\par}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{macro}{\smoothraggedrightfuzzfactor}
+% \begin{macrocode}
+\newcommand*{\smoothraggedrightfuzzfactor}{1.0}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\smoothraggedrightgenerator}
+% \begin{macrocode}
+\newcommand*{\smoothraggedrightgenerator}{triplet}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\smoothraggedrightleftskip}
+% \begin{macrocode}
+\newlength{\smoothraggedrightleftskip}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\smoothraggedrightparindent}
+% \begin{macrocode}
+\newlength{\smoothraggedrightparindent}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\smoothraggedrightragwidth}
+% \begin{macrocode}
+\newlength{\smoothraggedrightragwidth}
+\setlength{\smoothraggedrightragwidth}{2em}
+
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{ldimen}{\typog@fuzzwidth}
+% \begin{macrocode}
+\newdimen{\typog@fuzzwidth}
+
+% \end{macrocode}
+% \end{ldimen}
+%
+% \begin{environment}{smoothraggedrightpar}
+% The longest line will be \cs{linewidth} wide
+% unless overridden by optional argument~|linewidth|.
+%
+% \begin{macrocode}
+\define@key[typog]{smoothraggedrightpar}{linewidth}%
+ {\def\typog@@linewidth{#1}}
+
+\NewDocumentEnvironment{smoothraggedrightpar}{O{}}
+ {\edef\typog@@linewidth{\linewidth}%
+ \setkeys[typog]{smoothraggedrightpar}{#1}%
+% \end{macrocode}
+% Convert generator name to an integer suitable for \cs{ifcase}.
+% \begin{macrocode}
+ \edef\typog@@generatorchoice{%
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{triplet}=\z@
+ 0%
+ \else
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{quintuplet}=\z@
+ 1%
+ \else
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{septuplet}=\z@
+ 2%
+ \else
+ \PackageError{typog}
+ {smoothraggedright: unknown generator name}
+ {valid generator names are triplet, quintuplet, and septuplet}%
+ \fi
+ \fi
+ \fi}%
+% \end{macrocode}
+% Obey to the indentation prescribed by any list environment.
+% \begin{macrocode}
+ \let\typog@@smoothraggedrightleftskip=\smoothraggedrightleftskip
+ \ifnum\@listdepth>0
+ \addtolength{\typog@@smoothraggedrightleftskip}{\leftmargin}%
+ \fi
+% \end{macrocode}
+% Scale the fuzz-width by the user's factor.
+% Later we shall rescale again specifically for each generator.
+% \begin{macrocode}
+ \typog@fuzzwidth=\smoothraggedrightfuzzfactor\smoothraggedrightragwidth
+% \end{macrocode}
+%
+% Now for the generator-specific code\dots
+% \begin{macrocode}
+ \ifcase\typog@@generatorchoice
+% \end{macrocode}
+%
+% |generator=triplet| produces a \doublequotes{short line -- long line -- middle length line}~sequence.
+% \begin{macrocode}
+ \typog@fuzzwidth=.25\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=triplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapetriplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth}% (3)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ \or
+% \end{macrocode}
+%
+% |generator=quintuplet|.
+% \begin{macrocode}
+ \typog@fuzzwidth=.125\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=quintuplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapequintuplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr (\typog@@linewidth * 4 - \smoothraggedrightragwidth * 3) / 4
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth\relax}% (5)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (3)
+ {\glueexpr (\typog@@linewidth * 4 - \smoothraggedrightragwidth) / 4
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (4)
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ \or
+% \end{macrocode}
+%
+% |generator=septuplet|.
+%
+% Permutation \mbox{3 -- 6 -- 1 -- 5 -- 2 -- 7 -- 4}
+% looks \singlequotes{random} enough for our purposes.
+%
+% \begin{macrocode}
+ \typog@fuzzwidth=.08333\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=septuplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapeseptuplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr (\typog@@linewidth * 3 - \smoothraggedrightragwidth * 2) / 3
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (3)
+ {\glueexpr (\typog@@linewidth * 6 - \smoothraggedrightragwidth) / 6
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (6)
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth +
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ {\glueexpr (\typog@@linewidth * 3 - \smoothraggedrightragwidth) / 3
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (5)
+ {\glueexpr (\typog@@linewidth * 6 - \smoothraggedrightragwidth * 5) / 6
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth\relax}% (7)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (4)
+ \fi}
+ {\ifcase\typog@@generatorchoice
+ \endsmoothraggedrightshapetriplet
+ \or
+ \endsmoothraggedrightshapequintuplet
+ \or
+ \endsmoothraggedrightshapeseptuplet
+ \fi}
+
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{smoothraggedright}
+% \begin{macrocode}
+\NewDocumentEnvironment{smoothraggedright}{O{}}
+ {\PushPostHook{par}{\hskip-\parindent\smoothraggedrightpar[#1]\relax}}
+ {\par\PopPostHook{par}}
+
+% \end{macrocode}
+% \end{environment}
+%
+%
+% \iffalse
+%</package>
+% \fi
+%
+%
+% \addtocontents{toc}{\protect\end{multicols}}
+% \addtocontents{toc}{\endgroup}
+%
+%
+% \Finale
+%
+%
+%
+% \iffalse
+%<*example>
+\documentclass[a4paper]{article}
+
+\tracingonline=0
+
+\PassOptionsToPackage{dvipsnames}{xcolor}
+
+\usepackage{amsmath}
+\usepackage[main=USenglish, german]{babel}
+\usepackage{float}
+\usepackage[T1]{fontenc}
+\usepackage{fullwidth}
+\usepackage{hyphenat}
+\usepackage{mathtools}
+\usepackage[activate=true, verbose=true]{microtype}
+\usepackage{ragged2e}
+\usepackage[nobottomtitles*]{titlesec}\renewcommand*{\bottomtitlespace}{.2\textheight}
+\usepackage[debug, trackingttspacing]{typog}
+\usepackage{xcolor}
+
+\usepackage[loosest, proportional, scaled=1.064]{erewhon}
+\usepackage[erewhon]{newtxmath}
+\usepackage[scaled=.95]{cabin}
+\usepackage{inconsolata}
+\usepackage{setspace}\setstretch{1.08333}
+
+
+\def\xsfdefault{\relax}
+{
+ \def\examplefont{6}
+
+ \ifcase\examplefont % 0 -- document's default sans-serif font (e.g., ecrm1000)
+ \gdef\examplefontname{default}
+ \global\let\xsf=\sf
+ \global\let\xsfdefault=\sfdefault
+ \or % 1 -- Nunito
+ \gdef\examplefontname{Nunito}
+ \usepackage{nunito}
+ \xdef\xsfdefault{\rmdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 2 -- OpenSans
+ \gdef\examplefontname{OpenSans}
+ \usepackage[defaultsans]{opensans}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 3 -- Noto Sans
+ \gdef\examplefontname{OpenSans}
+ \usepackage[sfdefault]{noto}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 4 -- Roboto
+ \gdef\examplefontname{Roboto}
+ \usepackage[sfdefault]{roboto}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 5 -- Montserrat
+ \gdef\examplefontname{Montserrat Alternate}
+ \usepackage[alternates]{montserrat}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \or % 6 -- Inter
+ \gdef\examplefontname{Inter}
+ \usepackage[sfdefault]{inter}
+ \xdef\xsfdefault{\sfdefault}
+ \gdef\xsf{\let\sfdefault=\xsfdefault\sf}
+ \else
+ \SelectedUnknownExampleFont
+ \fi
+
+ \typeout{typog-example: font for examples: `\xsfdefault'}%
+}
+
+
+\usepackage{hyperref}
+\usepackage{cleveref}
+
+
+\hypersetup{
+ citecolor = CadetBlue,
+ colorlinks = true,
+ linkcolor = Blue,
+ linktocpage = true,
+ pdfauthor={Dr. Christoph L. Spiel},
+ pdfkeywords={Examples,
+ LaTeX, typography, ligature, italic-correction, paragraph justification, sloppy, ragged},
+ pdfsubject={Examples for typographic fine-tuning of LaTeX},
+ pdftitle={Examples for LaTeX package typog},
+ raiselinks = false,
+ urlcolor = Mulberry
+}
+
+
+\makeatletter
+\newcommand{\fs@myruled}{%
+ \fs@ruled
+ \def\@fs@capt##1##2{\floatc@ruled{##1\space\capitaldash*\space}{\fussy ##2}}%
+ \def\@fs@pre{\hrule height.8pt depth0pt \kern4pt}%
+ \def\@fs@mid{\kern3pt\hrule\kern3pt}%
+ \def\@fs@post{\kern4pt\hrule\relax}%
+}
+\makeatother
+
+\floatstyle{myruled}
+\newfloat{exemplary}{htbp}{loe}[section]
+\floatname{exemplary}{Example}
+\Crefname{exemplary}{Example}{Examples}
+\crefname{exemplary}{Ex.}{Ex.}
+
+
+\newcommand*{\acronym}[1]{\mbox{\letterspacecapitals{\MakeUppercase{#1}}}}
+\newcommand*{\bibauthor}[1]{\textsc{#1}}
+\newcommand*{\bibtitle}[1]{\textit{#1}}
+\newcommand*{\bottomstrut}{\rule[-.5em]{0pt}{0pt}}
+\newcommand*{\code}[1]{{\ttfamily\hyphenchar\font=`\-\relax #1}}
+\newcommand*{\doublequotes}[1]{\doubleguillemetright#1\doubleguillemetleft}
+\newcommand*{\eTeX}{\mbox{\(\epsilon\)-\TeX}}
+\newcommand*{\letterspacecapitals}[1]{\textls[30]{#1}}
+\newcommand*{\metavar}[1]{\textit{#1}}
+\newcommand*{\packagename}[1]{\mbox{\textsf{#1}}}
+\newcommand*{\propername}[1]{\mbox{\textsc{\textls[25]{#1}}}}
+\newcommand*{\sample}[1]{\mbox{`\texttt{#1}'}}
+\newcommand*{\singlequotes}[1]{\singleguillemetright#1\singleguillemetleft}
+\newcommand*{\topstrut}{\rule{0pt}{1.25em}}
+\newcommand*{\visualpar}{\,\P\quad}
+
+\newlength{\emreference}
+\AtBeginDocument{\setlength{\emreference}{\fontdimen6\font}}
+\newrobustcmd*{\milliem}[1]
+ {\ifdim #1=0pt
+ #1%
+ \else
+ \generictextfraction{\the\numexpr\dimexpr (#1) * 1000 / \emreference}{1000}\:em%
+ \fi}
+
+\newcommand*{\generictextfraction}[2]
+ {\raisebox{.4em}[0pt]{\scriptsize #1}%
+ \kern-.05em\textfractionsolidus\kern-.05em
+ \raisebox{-.15em}[0pt][0pt]{\scriptsize #2}}
+
+\newcommand*{\leftmarker}{\rule{.2em}{.1pt}\rule{.1pt}{.667em}}
+\newcommand*{\rightmarker}{\rule{.1pt}{.667em}\rule{.2em}{.1pt}}
+\newcommand*{\indicatewidth}[1]{\mbox{\leftmarker #1\rightmarker}}
+
+\newcommand*{\maxipagerule}{\medskip\hrule\medskip}
+\newenvironment*{maxipage*}
+ {\par
+ \noindent
+ \fullwidthsetup{leftmargin=-\marginparsep - \marginparwidth,
+ width=\textwidth + 2\marginparsep + 2\marginparwidth}
+ \begin{fullwidth}%
+ \vspace*{1pt}% Why is some vspace necessary?
+ \parskip=.5\baselineskip}
+ {\par
+ \end{fullwidth}%
+ \par}
+\newenvironment*{maxipage}
+ {\par
+ \noindent
+ \fullwidthsetup{leftmargin=-\marginparsep - \marginparwidth,
+ width=\textwidth + 2\marginparsep + 2\marginparwidth}
+ \begin{fullwidth}%
+ \maxipagerule
+ \parskip=.5\baselineskip}
+ {\par
+ \vskip\parskip
+ \maxipagerule
+ \end{fullwidth}%
+ \par}
+
+
+\newlength{\examplewidth}
+\setlength{\examplewidth}{160pt}
+
+\newcommand*{\texbooktolerancesample}
+ {If you want to avoid overfull boxes at all costs without trying to fix them manually,
+ you might be tempt\-ed to set \texttt{tol\-er\-ance=\allowbreak10000}; this allows
+ arbitrarily bad lines to be acceptable in tough situations. But infinite tolerance
+ is a bad idea, because \TeX{} doesn't distinguish between terribly bad and
+ preposterously horrible lines. Indeed, a tolerance of 10000 encourages \TeX{} to
+ concentrate all the badness in one place, making one truly unsightly line instead of
+ two moderately bad ones, because a single ``write-off'' produces fewest total
+ demerits according to the rules.}
+ %There is a much better way to get the desired effect:~[\dots]
+\newcommand*{\texbooktolerancesamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~107]{knuth:1986}.}}
+
+\newcommand*{\texbookparfillskipsample}
+ {We still haven't discussed the special trick that allows the final line of a paragraph
+ to be shorter than the others. Just before \TeX{} begins to choose breakpoints,
+ it does two important things: [\dots]}
+\newcommand*{\texbooklongparfillskipsample}
+ {We still haven't discussed the special trick that allows the final line of a paragraph
+ to be shorter than the others. Just before \TeX{} begins to choose breakpoints,
+ it does two important things: (1)~If the final item of the current horizontal list is glue,
+ that glue is discarded. (The reason is that a blank space often gets into a token list just
+ before \code{\char92par} or just before \code{\char36\char36}, and this blank space should not be
+ part of the paragraph.) (2)~Three or more items are put at the end of the
+ current horizontal list~[\dots]}
+\newcommand*{\texbookparfillskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~99n]{knuth:1986}.}}
+
+\newcommand*{\texbookparshapeskipsample}
+ {It's possible to control the length of lines in a much more general way, if simple
+ changes to \code{\string\leftskip} and \code{\string\rightskip} aren't flexible enough for your
+ purposes. For example, a semicircular hole has been cut out of the present paragraph,
+ in order to make room for a circular illustration that contains some of
+ Galileo's immortal words about circles; all of the line breaks in this
+ paragraph and in the circular quotation were found by \TeX's line-breaking algorithm.
+ You can specify a essentially arbitrary paragraph shape, by saying
+ \code{parshape}=\metavar{number}, where the \metavar{number} is a positive integer~\(n\),
+ followed by \(2n\)~\metavar{dimen} specifications.}
+\newcommand*{\texbookparshapeskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~101]{knuth:1986}.}}
+
+\newcommand*{\texbookbaselineskipsample}
+ {When you are typsetting a document that spans several pages, it's generally best to
+ define \code{\string\baselineskip} so that it cannot stretch or shrink, because
+ this will give more uniformity to the pages. A small variation in the distance
+ between the baselines---say only half a point---can make a substantial difference
+ in the appearance of the type, since it significantly affects the proportion of
+ white to black. On the other hand, if you are preparing a one-page document, you
+ might want to give the baselineskip some stretchability, so that \TeX{} will help
+ you fit the copy on the page.}
+\newcommand*{\texbookbaselineskipsamplecredits}
+ {\medskip\noindent
+ \textsl{The sample text was taken from The~\TeX{}book~\cite[p.~78]{knuth:1986}.}}
+
+
+
+\newcommand*{\examplepreset}{\microtypesetup{activate=false}}
+\newcommand*{\examplesetup}{\frenchspacing\xsf\small\fussy}
+\newcommand*{\exampleparbox}[2][n/a]
+ {\begin{typoginspect}{#1}
+ \examplepreset
+ \parbox[t]{\examplewidth}{\examplesetup #2}%
+ \end{typoginspect}}
+\newcommand*{\examplesep}{\hspace*{20pt}}
+\def\fontnameandweightinfo#1{%
+ {\def\projectoutfontname##1-##2-##3\relax{##1~\lowercase{##2}}%
+ \global\expandafter\edef\csname#1\endcsname{\expandafter\projectoutfontname\fontname\font\relax}}}
+\newcommand*{\examplefontinformation}
+ {\smallskip
+ \examplesetup
+ \fontnameandweightinfo{exfontnameinfo}%
+ \fontsizeinfo{exfontsizeinfo}%
+ The font used in this example is \exfontnameinfo, \exfontsizeinfo*.}
+
+
+\setcounter{tocdepth}{1}
+\setlength{\overfullrule}{3pt}
+\hbadness=-1
+
+
+\input{ushyphex}
+
+\hyphenation{
+ Double-guillemet-left
+ Double-guillemet-right
+ Double-quotes
+ Single-guillemet-left
+ Single-guillemet-right
+ Single-quotes
+ adj-demerits
+ allow-display-breaks
+ babel-hyphenation
+ base-line-skip
+ break-penalty
+ breakable-display
+ capital-hyphen
+ capital-times
+ cite-dash
+ club-penalties
+ cref-range-conjunction
+ display-break
+ display-widow-penalties
+ double-guillemet-right
+ double-hyphen-demerits
+ double-quotes
+ final-hyphen-demerits
+ inter-display-line-penalty
+ inter-text
+ kerned-hyphen
+ last-line-ragged-left
+ last-line-ragged-left-par
+ line-width
+ loose-ness
+ loose-spacing
+ make-at-letter
+ make-at-other
+ mar-gin-al
+ math-italics-correction
+ micro-type
+ number-dash
+ par-box
+ par-indent
+ parfillskip
+ pdf-string-def-Disable-Commands
+ post-display-penalty
+ pre-display-penalty
+ raise-capital-guillemets
+ raise-capital-times
+ raise-number-dash
+ set-font-expand
+ set-font-shrink
+ set-font-stretch
+ short-inter-text
+ single-guillemet-left
+ single-guillemet-right
+ single-quotes
+ slash-kern
+ slightly-sloppy-par
+ sloppy-par
+ smooth-ragged-right-fuzz-factor
+ smooth-ragged-right-par
+ smooth-ragged-right-shape-quintuplet
+ smooth-ragged-right-shape-septuplet
+ smooth-ragged-right-shape-triplet
+ space-skip
+ text-italics-correction
+ tight-spacing
+ tracing-boxes
+ tracing-para-graphs
+ vtie-bot
+ vtie-bot-disp
+ vtie-bot-disp-par
+ vtie-bot-disp-top-par
+ vtie-bot-par
+ vtie-top
+ vtie-top-par
+ widow-penalties
+}
+
+
+\SetExpansion[context=sloppy, stretch=30, shrink=60, step=5]{encoding={OT1, T1, TS1}}{}% p15
+\SetTracking{encoding=*, shape=sc}{20}
+
+
+\begin{document}
+\fussy
+\lastlinefit=1000
+\nonfrenchspacing
+
+\begin{center}
+ \Huge\bf\sf
+ TypoG Examples
+\end{center}
+
+\bigskip
+
+\noindent
+The section numbers correspond to the subsections of section~3
+in the official documentation of package~\packagename{typog}.
+
+\bigskip
+
+\tableofcontents
+
+
+\clearpage
+\listof{exemplary}{Examples}
+
+
+\clearpage
+\noindent
+Unless otherwise noted the font used in the examples is \singlequotes{\examplefontname}.
+
+\bigskip
+
+\section{Information}
+
+\code{\string\fontsizeinfo} --\fontsizeinfo{docsizeinfo}
+At this point of the document, the font~size
+and the line~spacing are \docsizeinfo*~(w/o~units).
+For footnotes however, the current sizes are%
+\footnote{This is the footnote where we get the sizes from.\fontsizeinfo{footsizeinfo}}
+\footsizeinfo.
+
+Next we show a comparison of different font sizes and line spacings
+decorated with the results of \code{\string\fontsizeinfo}.
+
+\medskip
+
+\begin{maxipage}
+ \setstretch{1}
+ \newcommand*{\baselineskipdoc}%
+ {Macro \code{\string\baselineskip} is a length command which
+ specifies the minimum space between the bottom of two
+ successive lines in a paragraph. Its value may be
+ automatically reset by \LaTeX, for example, by font
+ changes in the text.}
+ \renewcommand*{\examplefontname}{Merriweather}
+ Different font sizes and line spacings exemplified with the \examplefontname~font.
+
+ \smallskip
+
+ \begingroup
+ \fontfamily{Merriwthr-TLF}\selectfont
+ \noindent
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{8.5}{12}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfotight}}
+ \hfill
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{10}{12}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfo}}
+ \hfill
+ \parbox[t]{.31\linewidth}%
+ {\fontsize{10}{13.5}\selectfont
+ \baselineskipdoc
+ \fontsizeinfo{examplesizeinfoloose}}
+ \endgroup
+
+ \medskip
+
+ \noindent
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfotight*}
+ \hfill
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfo*}
+ \hfill
+ \parbox[t]{.31\linewidth}{\examplefontname~\examplesizeinfoloose*}
+\end{maxipage}
+
+\noindent Starred form eats spaces? \examplesizeinfo* .
+
+
+\section{Hyphenation}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\mbox+\string\breakpoint*} \\
+ \mbox{(pre-)}\breakpoint*Hilbert space}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \code{\string\breakpoint*} \\
+ (pre-)\breakpoint*Hilbert space}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \code{\string\breakpoint} \\
+ (pre-)\breakpoint Hilbert space}
+\end{quote}
+
+\noindent Starred form eats spaces? a\breakpoint* b. Unstarred: a\breakpoint b.
+
+\medskip
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \begin{hyphenmin}{6}
+ Set minimum hyphenation values for both \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin}: \the\lefthyphenmin{} and \the\righthyphenmin.
+ \end{hyphenmin}}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ \begin{hyphenmin}[4]{5}
+ Set minimum hyphenation values for \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin} separately: \the\lefthyphenmin{} and \the\righthyphenmin.
+ \end{hyphenmin}}
+ \hspace{100pt}
+ \parbox[t]{0pt}{%
+ Returned to the default values for \code{\string\lefthyphenmin} and
+ \code{\string\righthyphenmin}: \the\lefthyphenmin{} and \the\righthyphenmin.}
+\end{quote}
+
+
+\section{Disable\kernedslash*Break Ligatures}
+
+\begin{center}
+ \begin{tabular}{@{}ll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Macro} & Result \\
+ \hline
+ n/a &
+ fine affirmation of baffling flavors \\
+ \code{\string\nolig*} &
+ f\nolig*ine af\nolig*f\nolig*irmation of baf\nolig*f\nolig*ling f\nolig*lavors \\
+ \code{\string\nolig} &
+ f\nolig{}ine af\nolig{}f\nolig{}irmation of baf\nolig{}f\nolig{}ling f\nolig{}lavors \\
+ \code{\string\nolig*[75]} & of\nolig*[75]f\nolig*[75]ice
+ \end{tabular}
+\end{center}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\nolig*} \\
+ bi\nolig*{}jection}
+ \hspace{60pt}
+ \parbox[t]{0pt}{%
+ \code{\string\nolig} \\
+ bi\nolig{}jection}
+\end{quote}
+
+\noindent Starred form eats spaces? f\nolig* i, f\nolig*[0] i.
+
+
+\section{Manual Italic Correction}
+
+\paragraph{Text Mode.}
+
+The italic correction of the current font is \the\fontdimen1\font/pt.
+
+We demonstrate the effect of \code{\string\itcorr} with a pair of bookends:
+uncorrected italics: \indicatewidth{\it X},
+\TeX-corrected (\code{\string\/}): \indicatewidth{\it X\/},
+and \code{\string\itcorr\{7\}}: \indicatewidth{\it X\itcorr{7}}.
+
+Correction~0: \indicatewidth{\itcorr*{0}};
+corr.~3: \indicatewidth{\itcorr{3}}, \indicatewidth{\itcorr*{3}} (starred);
+corr.~\textminus6: \indicatewidth{\itcorr{-6}}.
+
+\paragraph{Mathematical Mode.}
+
+Uncorrected: \([f]\),
+corrected: \([\itcorr{1} f\itcorr{1}]\)
+
+Correction~0: \indicatewidth{\(\itcorr{0}\)};
+corr.~3: \indicatewidth{\(\itcorr{3}\)};
+corr.~\textminus6: \indicatewidth{\(\itcorr{-6}\)}.
+
+
+\section{Apply Extra Kerning}
+
+
+\subsection{Slash}
+
+The slash with some extra space around it can be helpful for certain pairs,
+as for example years or names.
+
+\begin{center}
+ \begin{tabular}{@{}ll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Macro} & Result \\
+ \hline
+ n/a & 1991/1992,
+ New~York/NY, Korringa/Kohn/Rostoker \\
+ \code{\string\kernedslash} &
+ 1991\kernedslash1992, New~York\kernedslash{}NY, Korringa\kernedslash{}Kohn\kernedslash{}Rostoker \\
+ \end{tabular}
+\end{center}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash*} \\
+ 1991\kernedslash*1992,
+ New~York\kernedslash*NY,
+ Korringa\kernedslash*Kohn\kernedslash*Rostoker}
+ \hspace{120pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash} \\
+ 1991\kernedslash{}1992,
+ New~York\kernedslash{}NY,
+ Korringa\kernedslash{}Kohn\kernedslash{}Rostoker}
+\end{quote}
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \parbox[t]{0pt}{%
+ \code{\string\kernedslash*}\code{\string\nobreak} \\
+ 1991\kernedslash*\nobreak{}1992,
+ New~York\kernedslash*\nobreak{}NY,
+ Korringa\kernedslash*Kohn\kernedslash*\nobreak{}Rostoker}
+ \hspace{140pt}
+ \parbox[t]{0pt}{%
+ \code{\string\allowhyphenation\string\kernedslash} \\
+ 1991\kernedslash{}1992,
+ New~York\kernedslash{}NY,
+ Korringa\allowhyphenation\kernedslash{}Kohn\kernedslash{}Rostoker}
+\end{quote}
+
+\noindent Starred form eats spaces? p\kernedslash* q.
+
+
+\subsection{Hyphen}
+
+Uncorrected
+
+\begin{quote}
+ \(K\)-vector space, \(g\)-factor, \(f\)-function
+\end{quote}
+
+\noindent Corrected
+
+\begin{quote}
+ \typogsetup{raisecapitalhyphen=.075em, raiseguillemets=.05em}
+ \(K\)\leftkernedhyphen{-75}vector space,
+ \(g\)\leftkernedhyphen{-25}factor,
+ \(f\)\leftkernedhyphen{-100}function
+ %% \(G\)\kernedhyphen[*]{50}{-50}Wirkung,
+ %% \(G\)\leftkernedhyphen{50}äquivalent,
+ %% \(K\)\kernedhyphen[*]{-50}{-50}Vektorraum,
+ %% \(K\)\kernedhyphen{-50}{-25}bilinear,
+ %% \propername{Young}\rightkernedhyphen{-50}Tableaux,
+ %% \singlequotes{Bra}\kernedhyphen[50]{50}{-50}Vektor,
+ %% \singlequotes{Ket}\kernedhyphen[50]{50}{-50}Vektor,
+ %% halbzahlige~\(l\)\kernedhyphen{50}{-50}Werte.
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+
+ \parbox[t]{0pt}{hyphen~\mbox{`\code{-}'} \\ self-energy}
+ \hspace{80pt}
+ \parbox[t]{0pt}{\code{\string\hyp} \\ self\hyp{}energy}
+ \hspace{60pt}
+ \parbox[t]{0pt}{\code{\string\kernedhyphen*} \\ self\kernedhyphen*{5}{-5}energy}
+ \hspace{80pt}
+ \parbox[t]{0pt}{\code{\string\kernedhyphen} \\ self\kernedhyphen{5}{-5}energy}
+\end{quote}
+
+\noindent If a \code{\string\kernedhyphen} goes astray in a math environment,
+it decays to an ordinary minus with appropriate kerning:
+\(G \kernedhyphen{-30}{-50} V\)\!.
+
+
+\section{Raise Selected Characters}
+
+\subsection{Capital Hyphen}
+
+\newlength{\exemplaryraisecapitalhyphen}
+\setlength{\exemplaryraisecapitalhyphen}{.6667pt}
+With the standard hyphen we get
+
+\begin{quote}
+ \begin{otherlanguage}{german}
+ \acronym{NMR}-Spektroskopie,
+ \acronym{SI}-Einheit,
+ \(G\)-Modul, and
+ \(K\)-Vektorraum,
+ \end{otherlanguage}
+\end{quote}
+
+\noindent whereas with raising the hyphen by \the\exemplaryraisecapitalhyphen{}
+when calling \code{\string\capitalhyphen}, we arrive at
+
+\begin{quote}
+ \begin{otherlanguage}{german}
+ \typogsetup{raisecapitalhyphen=.075em}
+
+ \acronym{NMR}\capitalhyphen{}Spektroskopie,
+ \acronym{SI}\capitalhyphen{}Einheit,
+ \(G\)\capitalhyphen{}Modul, and
+ \(K\)\capitalhyphen{}Vektorraum
+ (even better with \code{\string\kernedhyphen}
+ and the star-option for the correct raise-amount:
+ \(K\)\leftkernedhyphen[*]{-100}Vektorraum).
+ \end{otherlanguage}
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \begin{otherlanguage}{german}
+ \parbox[t]{0pt}{%
+ \code{\string\capitalhyphen*} \\
+ \acronym{NMR}\capitalhyphen*{}Spektroskopie
+ }
+ \hspace{120pt}
+ \parbox[t]{0pt}{%
+ \code{\string\capitalhyphen} \\
+ \acronym{NMR}\capitalhyphen{}Spektroskopie
+ }
+ \end{otherlanguage}
+\end{quote}
+
+\noindent Starred form eats spaces?
+{\typogsetup{raisecapitalhyphen=.075em}
+ V\capitalhyphen* W.}
+
+
+\subsection{Capital Dash}
+
+\newlength{\exemplaryraisecapitaldash}
+\setlength{\exemplaryraisecapitaldash}{.075em}
+
+Compare the result of plain~\code{\string\textendash}
+
+\begin{quote}
+ A\textendash M, N\textendash Z, C1\,\textendash\,C4, LEED\:\textendash\:STM
+\end{quote}
+
+\noindent with \code{\string\capitaldash}:
+
+\begin{quote}
+ \typogsetup{raisecapitaldash=\exemplaryraisecapitaldash}
+
+ A\capitaldash{}M, N\capitaldash{}Z, C1\,\capitaldash\,C4, LEED\:\capitaldash\:STM
+\end{quote}
+
+\noindent where the en-dash has been raised by \milliem{\exemplaryraisecapitaldash}.
+
+Starred form eats spaces? V\capitaldash* W.
+
+
+\subsection{Number Dash}
+
+\newlength{\exemplaryraisefiguredash}
+\setlength{\exemplaryraisefiguredash}{.6667pt}
+Compare the result of plain~\code{\string\textendash}
+
+\begin{quote}
+ 3--5, 81--82, 485--491
+\end{quote}
+
+\noindent with \code{\string\figuredash}:
+
+\begin{quote}
+ \typogsetup{raisefiguredash=\exemplaryraisefiguredash}
+ 3\figuredash 5, 81\figuredash 82, 485\figuredash 491
+\end{quote}
+
+\noindent where the en-dash has been raised by \the\exemplaryraisefiguredash.
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \typogsetup{raisefiguredash=\exemplaryraisefiguredash}
+ \parbox[t]{0pt}{%
+ \code{\string\figuredash*} \\
+ 3\figuredash*5, 81\figuredash*82, 485\figuredash*491
+ }
+ \hspace{80pt}
+ \parbox[t]{0pt}{%
+ \code{\string\figuredash} \\
+ 3\figuredash 5, 81\figuredash 82, 485\figuredash 491
+ }
+\end{quote}
+
+\noindent Starred form eats spaces? 44\figuredash* 55.
+
+
+\subsection{Multiplication Sign \capitaldash{} Times~``\texttimes''}
+
+\newlength{\exemplaryraisetimes}
+\setlength{\exemplaryraisetimes}{.6667pt}
+The problem with a too-low multiplication sign arises
+for example with matrices of a given, specific size.
+
+\noindent Uncorrected
+
+\begin{quote}
+ \acronym{LR}-mode: 2\texttimes2-matrix, \(N\)\texttimes\(M\)-matrix \\
+ Math-mode: \(2\times2\)-matrix, \(N\times M\)-matrix
+\end{quote}
+
+\noindent and corrected
+
+\begin{quote}
+ \typogsetup{raisecapitalhyphen=\exemplaryraisecapitalhyphen,
+ raisecapitaltimes=\exemplaryraisetimes}
+ \acronym{LR}-mode: 2\capitaltimes2-matrix, \(N\)\capitaltimes\(M\)-matrix \\
+ Math-mode: \(2\capitaltimes2\)-matrix, \(N\capitaltimes M\)-matrix.
+\end{quote}
+
+
+\subsection{Guillemets}
+
+\newcommand*{\tschicholdi}
+ {Use single quotes for a first quotation.}
+\newcommand*{\tschicholdii}
+ {Use double quotes for quotations within quotations.}
+
+\newcommand*{\frenchsinglequotes}[1]{\singleguillemetright #1\singleguillemetleft}
+\newcommand*{\Frenchsinglequotes}[1]{\Singleguillemetright #1\Singleguillemetleft}
+\newcommand*{\frenchdoublequotes}[1]{\doubleguillemetright #1\doubleguillemetleft}
+\newcommand*{\Frenchdoublequotes}[1]{\Doubleguillemetright #1\Doubleguillemetleft}
+
+\newcommand*{\frenchsinglequotesFR}[1]{\singleguillemetleft\,\allowhyphenation#1\,\singleguillemetright}
+\newcommand*{\FrenchsinglequotesFR}[1]{\Singleguillemetleft\,\allowhyphenation#1\,\Singleguillemetright}
+\newcommand*{\frenchdoublequotesFR}[1]{\doubleguillemetleft\,\allowhyphenation#1\,\doubleguillemetright}
+\newcommand*{\FrenchdoublequotesFR}[1]{\Doubleguillemetleft\,\allowhyphenation#1\,\Doubleguillemetright}
+
+\newlength{\exemplaryraiseguillemets}
+\setlength{\exemplaryraiseguillemets}{.05em}
+\newlength{\exemplaryraisecapitalguillemets}
+\setlength{\exemplaryraisecapitalguillemets}{.1em}
+
+We again compare the default implementation with the adjusted one.
+
+\begin{quote}
+ \frenchsinglequotes{\tschicholdi} \\
+ \frenchdoublequotes{\tschicholdii} \\
+ \Frenchsinglequotes{1}, \Frenchsinglequotes{2}, \Frenchsinglequotes{3}. \\
+ \Frenchdoublequotes{\letterspacecapitals{ABC}},
+ \Frenchdoublequotes{\letterspacecapitals{MN}},
+ \Frenchdoublequotes{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent Corrected by raising the glyphs by
+\milliem{\exemplaryraiseguillemets} and
+\milliem{\exemplaryraisecapitalguillemets}, respectively:
+
+\begin{quote}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+ \frenchsinglequotes{\tschicholdi} \\
+ \frenchdoublequotes{\tschicholdii} \\
+ \Frenchsinglequotes{1}, \Frenchsinglequotes{2}, \Frenchsinglequotes{3}. \\
+ \Frenchdoublequotes{\letterspacecapitals{ABC}},
+ \Frenchdoublequotes{\letterspacecapitals{MN}},
+ \Frenchdoublequotes{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent And the same using French typographic conventions:
+
+\begin{quote}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+ \frenchsinglequotesFR{\tschicholdi} \\
+ \frenchdoublequotesFR{\tschicholdii} \\
+ \FrenchsinglequotesFR{1}, \FrenchsinglequotesFR{2}, \FrenchsinglequotesFR{3}. \\
+ \FrenchdoublequotesFR{\letterspacecapitals{ABC}},
+ \FrenchdoublequotesFR{\letterspacecapitals{MN}},
+ \FrenchdoublequotesFR{\letterspacecapitals{XYZ}}.
+\end{quote}
+
+\noindent Line-break behavior
+
+\begin{quote}
+ \setlength{\overfullrule}{0pt}
+ \typogsetup{raiseguillemets=\exemplaryraiseguillemets,
+ raisecapitalguillemets=\exemplaryraisecapitalguillemets}
+
+ \newcommand*{\samplestring}{relation}
+
+ \parbox[t]{0pt}{\frenchsinglequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\Frenchsinglequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\frenchdoublequotes{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\Frenchdoublequotes{\samplestring}}
+
+ \smallskip
+
+ \parbox[t]{0pt}{\frenchsinglequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\FrenchsinglequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\frenchdoublequotesFR{\samplestring}}
+ \hspace{30pt}
+ \parbox[t]{0pt}{\FrenchdoublequotesFR{\samplestring}}
+\end{quote}
+
+
+\clearpage
+\section{Align Last Line}
+
+\subsection{Last Line Ragged Left/Flush Right}
+
+\Cref{ex:lastlineraggedleftpar} is a typical use of environment~\code{lastlineraggedleftpar}:
+A narrow paragraph gets typeset with full justification
+and put \code{\string\flushright} against the right margin as a whole.
+
+The layout may look more coherent if the last lines is moved to the right margin, too.
+
+\begin{exemplary}
+ \flushright
+ \caption[Justified -- flushright]
+ {\begin{typoginspectpar}{justified-flushright}Typeset a justified paragraph flushright and let
+ macro~\code{\string\lastlineraggedleft} shift the last line
+ over to the right-hand side.\label{ex:lastlineraggedleftpar}\end{typoginspectpar}}
+
+ \setlength{\examplewidth}{220pt}
+ \exampleparbox[lastlineraggedleftpar]{\lastlineraggedleftpar\texbookparfillskipsample}
+
+ \centering
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+
+\subsection{Last Line Centered}
+
+The situation shown in \cref{ex:lastlinecenteredpar} is
+more widespread than \cref{ex:lastlineraggedleftpar}
+because centered tables and figures are quite common.
+Their caption parboxes are centered too,
+which is where a centered last line might fortify the layout.
+
+Another possible use of environment~\code{lastlinecenteredpar} are the final lines of chapters~--
+in particular if the chapters' ends are marked with centered dingbats.
+
+\begin{exemplary}
+ \centering
+ \caption[Typeset a justified paragraph that is centered.]
+ {\lastlinecenteredpar
+ Typeset a justified paragraph that is centered.
+ This very caption uses \code{lastlinecenteredpar}
+ to have its last line centered as well.
+ Moreover, we put a nifty asterisk centered at the bottom of the sample text.
+ \label{ex:lastlinecenteredpar}}
+
+ \setlength{\examplewidth}{220pt}
+ \exampleparbox[lastlinecenteredpar]{\lastlinecenteredpar\texbookparfillskipsample}
+
+ \medskip\(\ast\)
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+
+\clearpage
+\section{Fill Last Line}
+
+\newcommand*{\abcsample}{abcd efgh ijkl mnop qrst uvwx yz12 3456}
+
+\begin{exemplary}
+ \def\sness{2}
+ \def\exparindent{25pt}
+ \setlength{\examplewidth}{235pt}
+
+ \centering
+ \caption[Plain paragraph vs.~\code{covernextindentpar}]
+ {Top example: Typeset a paragraph without correction of the last line.
+ Middle example: Paragraph corrected with \code{covernextindentpar}.
+ We set a \code{\string\parindent} of~\exparindent{} in both parboxes
+ and we \emph{must} increase the amount of glue in the paragraph
+ to reduce the penalty of stretching the last line under a \code{\string\fussy}~setting.
+ For the samples below, we have chosen \code{\string\slightlysloppy[\sness]}.
+ The \singlequotes{Alternative}, the bottom example,
+ shows the effect of \code{tightspacing};
+ no extra sloppyness is required there.}
+
+ \exampleparbox[covernextindentpar-reference]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[covernextindentpar]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \covernextindentpar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ Alternative\dots\hfill\smallskip
+
+ \exampleparbox[covernextindentpar-tightspacing]{%
+ \setlength{\parindent}{\exparindent}%
+ \begin{tightspacing}
+ \texbookparfillskipsample{} \abcsample
+ \end{tightspacing}}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \def\sness{2}
+ \def\exparindent{0pt}
+ \setlength{\examplewidth}{155pt}
+
+ \centering
+ \caption[Plain paragraph vs.~\code{covernextindentpar} (narrow)]
+ {Same comparison as the previous example,
+ but for a small linewidth and zippo~\code{\string\parindent}.
+ The left-hand side sample is uncorrected,
+ the right-hand side features \code{\string\covernextindentpar}.
+ The sloppyness level is~\sness{} for both samples.}
+
+ \exampleparbox[narrow-covernextindentpar-reference]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \texbookparfillskipsample{} \abcsample}
+ \qquad
+ \exampleparbox[narrow-covernextindentpar]{%
+ \setlength{\parindent}{\exparindent}%
+ \slightlysloppy[\sness]
+ \covernextindentpar[30pt]
+ \texbookparfillskipsample{} \abcsample}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \def\exparindent{10pt}
+ \setlength{\examplewidth}{233pt}
+
+ \centering
+ \caption[Prevent full last line]
+ {Sample~1: Typeset a paragraph without correction of the last line.
+ Sample~2: Paragraph corrected with \code{\string\openlastlinepar}.~-- Disappointing!
+ Sample~3: Same using macro~\code{\string\prolongpar}.
+ Sample~4: Alternative solution that simply increases the tracking by
+ \generictextfraction{2}{1000}\,em with~\code{setfonttracking}.
+ Sample~5: Alternative solution that increases the spacing with
+ \code{loosespacing}.}
+
+ \exampleparbox[openline-reference]{%
+ \setlength{\parindent}{\exparindent}
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[openlastlinepar]{%
+ \setlength{\parindent}{\exparindent}
+ \openlastlinepar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[prolongpar]{%
+ \setlength{\parindent}{\exparindent}
+ \prolongpar
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ Alternatives\dots\hfill\smallskip
+
+ \exampleparbox[openline-tracking]{%
+ \setlength{\parindent}{\exparindent}%
+ \setfonttracking{2}
+ \texbookparfillskipsample{} \abcsample}
+
+ \medskip
+
+ \exampleparbox[openline-spacing]{%
+ \setlength{\parindent}{\exparindent}%
+ \begin{loosespacing}
+ \texbookparfillskipsample{} \abcsample
+ \end{loosespacing}}
+
+ \texbookparfillskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+
+\clearpage
+\section{Spacing}
+
+\subsection{Narrow\kernedslash Wide Space}
+
+The current font's parameters are shown in \cref{tab:fontdim}.\footnote{For a concise and
+understandable explanation of the plethora of font parameters
+consult \propername{David Carlisle's} excellent post on \propername{StackExchange}:
+\href{https://tex.stackexchange.com/questions/88991/what-do-different-fontdimennum-mean}%
+ {What Do Different Fontdimennum Mean}.}
+
+\begin{table}[htp]
+ \centering
+ \caption{Important \code{\string\fontdimen} values of the current text font.
+ The middle column~(\#) states the number of the fontdimen.\bottomstrut}
+ \label{tab:fontdim}
+
+ \begin{tabular}{@{}lll@{}}
+ \hline
+ \multicolumn{1}{@{}l|}{Name} & \multicolumn{1}{l|}{\#} & Value \\
+ \hline
+ Interword space & 2 & \the\fontdimen2\font\topstrut \\
+ Interword stretch & 3 & \the\fontdimen3\font \\
+ Interword shrink & 4 & \the\fontdimen4\font \\
+ Extra space & 7 & \the\fontdimen7\font
+ \end{tabular}
+\end{table}
+
+\begin{center}
+ \setlength{\overfullrule}{0pt}
+ \newcommand*{\spacesampletext}[1]{some#1text#1with#1spaces\rule{0.1pt}{1em}}
+ \newsavebox{\narrowspacesample}
+ \sbox{\narrowspacesample}{\spacesampletext{\narrowspace}}
+ \newsavebox{\widespacesample}
+ \sbox{\widespacesample}{\spacesampletext{\widespace}}
+
+ \begin{tabular}{@{}ll@{\qquad}l@{}}
+ Compare & \spacesampletext{\space} & default space, natural glue \\
+ with & \usebox{\narrowspacesample} & \code{\string\narrowspace}, natural glue \\
+ {} & \makebox[\wd\narrowspacesample][l]{\hbox to 0pt{\spacesampletext{\narrowspace}}} &
+ \code{\string\narrowspace}, tight box \\
+ {} & \makebox[\wd\narrowspacesample][l]{\hbox spread 5pt{\spacesampletext{\narrowspace}}} &
+ \code{\string\narrowspace}, spread 5pt \\
+ and again & \spacesampletext{\space} & default space, natural glue \\
+ with & \usebox{\widespacesample} & \code{\string\widespace}, natural glue \\
+ {} & \makebox[\wd\widespacesample][l]{\hbox to 0pt{\spacesampletext{\widespace}}} &
+ \code{\string\widespace}, tight box \\
+ {} & \makebox[\wd\widespacesample][l]{\hbox spread 5pt{\spacesampletext{\widespace}}} &
+ \code{\string\widespace}, spread 5pt
+ \end{tabular}
+\end{center}
+
+\noindent Starred form eats spaces? Narrow\narrowspace* Space. Wide\widespace* Space.
+
+
+\subsection{Looser\kernedslash*Tighter}
+
+\Cref{ex:spacing-i,ex:spacing-ii} show \code{tightspacing} and \code{loosespacing} at work.
+
+\begin{exemplary}
+ \newcommand*{\sness}{3}
+ \newcommand*{\tlevel}{1}
+ \centering
+
+ \caption[Looser or tighter spacing -- sloppy]
+ {Both parboxes are typeset with \code{\string\slightlysloppy[\sness]},
+ the left one with default spacing,
+ the right one with \code{tightspacing[\tlevel]}.\label{ex:spacing-i}}
+
+ \exampleparbox[tightspacing-reference]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[tightspacing]{\slightlysloppy[\sness]\tightspacing[\tlevel]\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \newcommand*{\sness}{3}
+ \newcommand*{\llevel}{2}
+ \centering
+
+ \caption[Looser or tighter spacing -- sloppy]
+ {Both parboxes are typeset with \code{\string\slightlysloppy[\sness]},
+ the left one with default spacing,
+ the right one with \code{loosespacing[\llevel]}.\label{ex:spacing-ii}}
+
+ \exampleparbox[loosespacing-reference]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[loosespacing]{\slightlysloppy[\sness]\loosespacing[\llevel]\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+
+\clearpage
+\section{Microtype Front\capitalhyphen End}
+
+\subsection{Tracking}
+
+\newcommand*{\trackingsampletext}{%
+ This sentence contains an explicit call to \code{\string\textls}
+ with an optional argument of \((+200)\) to \textls[200]{DEMONSTRATE}
+ that this macro still works inside of \code{setfonttracking}.
+ Apart from that it is just some more text to exercise the macro.
+ Well, the explicit letterspacing example is particularly ugly.}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \def\extratracking{7}
+ \centering
+
+ \caption[Microtype: tracking]
+ {Use \packagename{microtype} to change the font tracking.
+ The sample on the left-hand side shows neutral tracking.
+ The one on the right-hand side received an extra tracking of
+ \generictextfraction{\extratracking}{1000}\,em.}
+
+ \exampleparbox[microtype-tracking-reference]{%
+ \fussy
+ \noindent
+ \trackingsampletext}
+ \qquad
+ \exampleparbox[microtype-tracking-stretch]{%
+ \begin{setfonttracking}{\extratracking}
+ \fussy
+ \noindent
+ \trackingsampletext
+ \end{setfonttracking}}
+
+ \examplefontinformation
+\end{exemplary}
+
+\newcommand*{\trackingsamplefontchangetext}{%
+ {\rm RM} {\sf SF} {\rm RM} {\tt TT} {\rm RM};
+ {\rm RM} {\it IT\/} {\rm RM};
+ {\rm RM} {\sc SC} {\rm RM}.
+ {\rm Rm} {\sf Sf} {\rm Rm} {\tt Tt} {\rm Rm};
+ {\rm Rm} {\it It\/} {\rm Rm};
+ {\rm Rm} {\sc Sc} {\rm Rm}.
+ {\rm rm} {\sf sf} {\rm rm} {\tt tt} {\rm rm};
+ {\rm rm} {\it it\/} {\rm rm};
+ {\rm rm} {\sc sc} {\rm rm}.}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \def\extratracking{1}
+ \centering
+
+ \caption[Microtype: tracking -- font changes]
+ {Check how font changes (serif, serif~italics, small-caps, sans~serif, typewriter)
+ interfere with the interword spacing.
+ The left sample has no tracking changes applied and serves as a reference,
+ whereas the right sample got an extra tracking of
+ \generictextfraction{\extratracking}{1000}\,em.\visualpar
+ The switch from and to typewriter, i.\,e., constant-width fonts
+ commonly is a source of spacing problems.}
+
+ \exampleparbox[microtype-tracking-font-changes-reference]{\trackingsamplefontchangetext}
+ \qquad
+ \exampleparbox[microtype-tracking-font-changes-stretch]{%
+ \begin{setfonttracking}{\extratracking}
+ \trackingsamplefontchangetext
+ \end{setfonttracking}}
+\end{exemplary}
+
+\noindent
+No contents: \leftmarker
+\begin{setfonttracking}{0}
+\end{setfonttracking}\rightmarker.
+
+
+\subsection{Font Expansion}
+
+\newcommand*{\expansionsample}
+ {By default, all characters of a font are allowed to be stretched or
+ shrunk by the same amount. However, it is also possible to limit
+ the expansion of certain characters if they are more sensitive to
+ deformation.
+ This is the purpose of the \code{\string\SetExpansion}~command.}
+
+\begin{exemplary}
+ \setlength{\examplewidth}{250pt}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \renewcommand*{\examplesetup}{\frenchspacing\small\fussy}
+
+ \centering
+
+ \caption[Microtype: font expansion]
+ {Use \packagename{microtype} to stretch or shrink a font.
+ The top sample uses \code{\string\setfontshrink} at level~3,
+ the middle sample is the unchanged reference
+ (which is allowed to shrink and expand),
+ and the bottom sample utilizes \code{\string\setfontstretch} at level~2.}
+
+ \exampleparbox[microtype-expansion-shrink]{%
+ \begin{setfontshrink}[3]
+ \noindent\expansionsample
+ \end{setfontshrink}}
+
+ \medskip
+
+ \exampleparbox[microtype-expansion-neutral]{%
+ \begin{setfontexpand}[0]
+ \noindent\expansionsample
+ \end{setfontexpand}}
+
+ \medskip
+
+ \exampleparbox[microtype-expansion-stretch]{%
+ \begin{setfontstretch}[2]
+ \noindent\expansionsample
+ \end{setfontstretch}}
+
+ \examplefontinformation
+\end{exemplary}
+
+\noindent
+No contents -- \code{setfontshrink}: \leftmarker
+\begin{setfontshrink}
+\end{setfontshrink}\rightmarker.
+
+\noindent
+No contents -- \code{setfontstretch}: \leftmarker
+\begin{setfontstretch}
+\end{setfontstretch}\rightmarker.
+
+\noindent
+No contents -- \code{setfontexpand}: \leftmarker
+\begin{setfontexpand}
+\end{setfontexpand}\rightmarker.
+
+\noindent
+No contents -- \code{nofontexpansion}: \leftmarker
+\begin{nofontexpansion}
+\end{nofontexpansion}\rightmarker.
+
+
+
+\subsection{Character Protrusion}
+
+\newcommand*{\zerodepthrule}
+ {\raisebox{0pt}[0pt][0pt]{\rule[-4.5\baselineskip]{.1pt}{4.25\baselineskip}}}
+
+\newcommand*{\protrusionsampletext}{%
+ \noindent
+ \zerodepthrule\hfill\zerodepthrule \\
+ 1\hfill 1 \\
+ .2\hfill 2. \\
+ --3\hfill 3-- \\
+ ---4\hfill 4---}
+
+\begin{exemplary}
+ \renewcommand*{\examplepreset}{\microtypesetup{activate=true}}
+ \renewcommand*{\examplesetup}{\frenchspacing\small\fussy}
+
+ \centering
+
+ \caption[Microtype: protrusion]
+ {Comparison of the \packagename{microtype} feature ``protrusion'' (left-hand side)
+ and \code{nocharprotrusion} (right-hand side).}
+
+ \exampleparbox[microtype-protrusion-reference]{%
+ \microtypesetup{protrusion=true}
+ \protrusionsampletext}
+ \qquad
+ \exampleparbox[microtype-protrusion-off]{%
+ \microtypesetup{protrusion=true}
+ \nocharprotrusion
+ \protrusionsampletext}
+
+ \medskip
+\end{exemplary}
+
+\noindent
+No contents -- \code{nocharprotrusion}: \leftmarker
+\begin{nocharprotrusion}
+\end{nocharprotrusion}\rightmarker.
+
+
+\clearpage
+\section{Sloppy Paragraphs}
+
+\Cref{ex:slightlysloppy-1,ex:slightlysloppy-2} put different amounts of ``sloppiness'' face to face.
+
+\begin{exemplary}
+ \setlength{\examplewidth}{180pt}
+ \def\sness{1}
+ \centering
+ \caption[Paragraphs typeset slightly sloppy~1]
+ {Paragraphs typeset slightly sloppy: \code{\string\slightlysloppy} vs.~\code{\string\fussy}.
+ The left parbox is typeset with \code{\string\slightlysloppy}
+ and \(\metavar{sloppiness} = \sness\), whereas the right sample
+ features the well known \code{\string\fussy} setting.
+ Both parboxes have a width of \the\examplewidth.\label{ex:slightlysloppy-1}}
+
+ \exampleparbox[fussy-vs-slightlysloppy]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[fussy-vs-slightlysloppy-reference]{\fussy\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+\begin{exemplary}
+ \setlength{\examplewidth}{150pt}
+ \def\sness{2}
+ \centering
+ \caption[Paragraphs typeset slightly sloppy~2]
+ {Paragraphs typeset slightly sloppy: \code{\string\slightlysloppy} vs.~\code{\string\sloppy}.
+ The left sample is features \code{\string\slightlysloppy} with \(\metavar{sloppiness} = \sness\),
+ the right sample is typeset with \code{\string\sloppy}.
+ Both parboxes have a width of \the\examplewidth.\label{ex:slightlysloppy-2}}
+
+ \exampleparbox[sloppy-vs-slightlysloppy]{\slightlysloppy[\sness]\texbooktolerancesample}
+ \qquad
+ \exampleparbox[sloppy-vs-slightlysloppy-reference]{\sloppy\texbooktolerancesample}
+
+ \texbooktolerancesamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+In conclusion all renderings of the text in
+\cref{ex:slightlysloppy-1} and \cref{ex:slightlysloppy-2}
+have their merits and their own flaws.
+
+
+\clearpage
+\section{Vertically Partially-Tied Paragraphs}
+
+\paragraph{\code{vtietoppar}}\leavevmode\par
+
+\begin{typoginspect}{vtietoppar}
+ \clubpenalty=150
+ \begin{vtietoppar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\clubpenalty} after
+ the first line of a paragraph.\footnote{Footnote of \code{vtietoppar}.}
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \end{vtietoppar}
+\end{typoginspect}
+
+\paragraph{\code{vtiebotpar}}\leavevmode\par
+
+\begin{typoginspect}{vtiebotpar}
+ \widowpenalty=150
+ \begin{vtiebotpar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\widowpenalty}
+ before the last line of the paragraph.\marginpar{A float!}
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \end{vtiebotpar}
+\end{typoginspect}
+
+\paragraph{\code{vtiebotdisp}}\leavevmode\par
+
+\begin{typoginspect}[tracingboxes]{vtiebotdisp}
+ \displaywidowpenalty=150
+ \begin{vtiebotdisp}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\displaywidowpenalty}
+ before the line immediately preceding a displayed equation.
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \[g H = H g \quad \text{for all} \enspace g \in G.\]
+ \end{vtiebotdisp}
+
+ Follow-up paragraph after and outside of the \code{vtiebotdisp}-environment.
+\end{typoginspect}
+
+\paragraph{\code{vtiebotdisptoppar}}\leavevmode\par
+
+\begin{typoginspect}{vtiebotdisptoppar}
+ \displaywidowpenalty=150
+ \begin{vtiebotdisptoppar}[2]
+ After breaking a paragraph into lines, \TeX{} computes the interline
+ penalties by adding the values of: \code{\string\displaywidowpenalty}
+ before the line immediately preceding a displayed equation.
+ \eTeX{} generalizes the concept of interline, club, widow, and display widow penalty
+ by allowing their replacement by arrays of penalty values.
+ \begin{breakabledisplay}
+ \begin{displaymath}
+ g H = H g \quad \text{for all} \enspace g \in G.
+ \end{displaymath}
+ \end{breakabledisplay}
+
+ In this example we need a paragraph that follows the displayed math.
+ So, we have to type some more text here
+ to be able to demonstrate the action of the environment.
+ \end{vtiebotdisptoppar}
+\end{typoginspect}
+
+
+\clearpage
+\section{Breakable Displayed Equations}
+
+\newcommand*{\binaryminus}{\mathbin{-}}
+\newcommand*{\diracadj}[1]{\overline{#1}}
+\newcommand*{\unaryminus}{{-}}
+
+\begin{typoginspect}{breakabledisplay}
+ \begin{breakabledisplay}
+ \begin{align*}
+ \diracadj{\psi}(x) \mathop{\partial_\mu} \psi(x)
+ \mapsto \diracadj{\psi'}(x) \mathop{\partial_\mu} \psi'(x)
+ &= e^{i \alpha(x)} \diracadj{\psi}(x) \mathop{\partial_\mu} \bigl( e^{\unaryminus i \alpha(x)} \psi(x) \bigr) \\
+ &= \underbrace{\diracadj{\psi}(x) \mathop{\partial_\mu} \psi(x)}_{\text{free particle}}
+ \mskip\medmuskip \binaryminus \mskip\medmuskip i \, \diracadj{\psi}(x)
+ \underbrace{\mathop{\partial_\mu} \bigl( \alpha(x) \bigr)}_{\mathclap{\text{vector field}}} \psi(x).
+ \end{align*}
+ \end{breakabledisplay}
+\end{typoginspect}
+
+
+\clearpage
+\section{\packagename{Setspace} Front-End}
+
+\fontsizeinfo{defaultsize}
+Current settings are \defaultsize{}
+%--\settoheight{\typogfontsize}{CEMNORSUVWXZ}
+and \code{\string\typogfontsize} is \the\typogfontsize.
+
+
+\newcommand*{\absbls}{12pt plus 1pt minus .5pt}
+\paragraph{\code{\string\setbaselineskip\{\absbls\}}}
+\resetbaselineskip
+\setbaselineskip{10pt + 2.75pt}% addition
+\setbaselineskip{10.5pt * 100 / 105}% scaling
+\setbaselineskip{11.8pt * 85 / 100}% scaling
+\setbaselineskip{\absbls}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+
+\newcommand*{\relbls}{130}
+\paragraph{\code{\string\setbaselineskippercentage\{\relbls\}}}
+\setbaselineskippercentage{1 + 2 + .3333 * 100 + 100 * 0.6667}% float expression
+\setbaselineskippercentage{\relbls}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+
+\newcommand*{\absled}{1.5pt}
+\paragraph{\code{\string\setleading\{\absled\}}}
+\setleading{1pt / -2.0}% negative leading
+\setleading{\absled}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+
+\newcommand*{\relled}{30}
+\paragraph{\code{\string\setleadingpercentage\{\relled\}}}
+\setleadingpercentage{10 - 25 / 2}% negative leading
+\setleadingpercentage{\relled}
+\fontsizeinfo{baselinesetsize}
+New settings: \baselinesetsize.
+
+\texbookbaselineskipsample
+
+\medskip
+
+\setstretch{1}
+\texbookbaselineskipsamplecredits
+
+
+\clearpage
+\section{Smooth Ragged}
+
+\begin{exemplary}
+ \newcommand*{\ragwidth}{10pt}
+ \centering
+ \caption[Comparison of ragged right typesetting]
+ {Comparison of ragged right typesetting.
+ The first example uses \code{RaggedRight} of \packagename{ragged2e}
+ the second \code{smoothraggedrightpar} of \packagename{typog}.
+ Both examples share a \code{\string\fussy}~setting and
+ a \ragwidth~wide ragged right margin.\label{ex:smoothraggedright}}
+
+ \setlength{\RaggedRightRightskip}{0pt plus \ragwidth}
+
+ %\def\smoothraggedrightgenerator{quintuplet}
+ %\def\smoothraggedrightgenerator{septuplet}
+ \setlength{\smoothraggedrightragwidth}{\ragwidth}
+ %\def\smoothraggedrightfuzzfactor{.667}
+
+ \iffalse
+ \begin{quote}
+ \begin{RaggedRight}\examplesetup
+ \texbookparshapeskipsample
+ \end{RaggedRight}
+ \end{quote}
+
+ \begin{quote}
+ \begin{smoothraggedrightpar}\examplesetup
+ \texbookparshapeskipsample
+ \end{smoothraggedrightpar}
+ \end{quote}
+ \else
+ \exampleparbox[RaggedRight-reference]{\RaggedRight\texbooktolerancesample}
+ \qquad
+ \exampleparbox[smoothraggedrightpar]{\smoothraggedrightpar\texbooktolerancesample}
+ \fi
+
+ \texbookparshapeskipsamplecredits
+
+ \examplefontinformation
+\end{exemplary}
+
+
+ %--\setlength{\smoothraggedrightparindent}{25pt}
+ %--\setlength{\parindent}{0pt}
+
+\noindent
+\code{\string\parindent}=\the\parindent,
+visually: \rule{.1pt}{.8em}\kern\parindent\rule{.1pt}{.8em};
+
+\noindent
+\code{\string\smoothraggedrightleftskip}=\the\smoothraggedrightleftskip.
+\code{\string\smoothraggedrightparindent}=\the\smoothraggedrightparindent.
+\smallskip
+
+{
+ %--\setlength{\smoothraggedrightragwidth}{8pt}
+ \begin{smoothraggedright}
+ \texbooktolerancesample
+
+ \texbooktolerancesample
+ \end{smoothraggedright}
+}
+
+\medskip
+
+{
+ \setlength{\smoothraggedrightragwidth}{15pt}
+
+ \newcommand*{\definitionnilpotent}{%
+ Eine Abbildung oder ein Operator~\(A\)
+ heißen nilpotent vom Grad~\(k\), falls \(k \in N\)
+ die kleinste Zahl ist, für die gilt: \(A^k = 0\).}
+
+ \begin{otherlanguage}{german}
+ \parbox[t]{60pt}{\fussy\RaggedRight\definitionnilpotent}
+ \hspace{40pt}
+ \parbox[t]{60pt}{\fussy\smoothraggedright\definitionnilpotent}
+ \end{otherlanguage}
+}
+
+\clearpage
+\begin{RaggedRight}
+ \begin{thebibliography}{0}
+ \bibitem{knuth:1986}
+ \bibauthor{Knuth, D.~E.},
+ \bibtitle{The \TeX{}book},
+ Vol.~A of Computers\&Typesetting,
+ Addison Wesley, Reading\kernedslash*MA,
+ 1986.
+ \end{thebibliography}
+\end{RaggedRight}
+\end{document}
+%</example>
+% \fi
+%
+%
+%
+% \iffalse
+%<*nomicrotype>
+\documentclass[]{article}
+
+
+\usepackage[english]{babel}
+
+\usepackage{csquotes}
+\DeclareQuoteStyle{typog-guillemets}
+ {\doubleguillemetright}
+ {\doubleguillemetleft}
+ {\singleguillemetright}
+ {\singleguillemetleft}
+
+\usepackage[]{typog}
+
+
+\newcommand*{\packagename}[1]{\mbox{\textsf{#1}}}
+
+
+\begin{document}
+\begin{center}
+ \Huge\bf\sf
+ TypoG Examples \\
+ without Package~\packagename{microtype}
+\end{center}
+
+\bigskip
+
+\noindent
+This example \LaTeX-document uses package~\packagename{typog}
+\emph{without} package~\packagename{microtype}.
+
+We want \packagename{typog} to be as usable as possible even without
+the nice features that \packagename{microtype} offers.
+After all \packagename{typog} is just a front-end for it.
+
+As we are testing a special configuration here anyhow,
+we hook up our quotes with package~csquotes
+to check whether they interact ok.
+{\setquotestyle{typog-guillemets}%
+ \enquote{This is the outer part of the phrase
+ which contains the \enquote{inner part}.}}
+\end{document}
+%</nomicrotype>
+% \fi
+%
+%
+%
+% \iffalse
+%<*teximan2latex>
+## Remove all lines we neither need nor want.
+/^\\input /d
+/^@anchor/d
+/^@bye/d
+/^@documentencoding/d
+/^@node/d
+/^@setfilename/d
+/^@settitle/d
+/^@top/d
+/@menu/,/@end menu/d
+
+## Convert sectioning macros to our own hierarchy.
+s/^@chapter \(.*\)$/\\subsection*{\\textls[40]{\1}}/
+s/^@section \(.*\)$/\\subsubsection*{\1}/
+
+## Make `@asis' list resemble the Texinfo format.
+s/@table @asis/\\begin{list}{}{\\itemindent=-20pt\\leftmargin=20pt}/
+s/@end table/\\end{list}/
+
+## Indenting by four spaces generates a `verbatim' environment.
+s/@verbatim/\\begin{verbatim}/
+s/@end verbatim/\\end{verbatim}/
+
+## We substitute @display for our maxipage environment.
+s/@display/\\begin{maxipage}/
+s/@end display/\\end{maxipage}/
+
+## The argument format of the URL macro is different.
+s/@url{\([^,]*\), \([^}]*\)}/\\href{\1}{\2}/g
+
+## Use our own markup.
+s/\.\.\./\\dots{}/g
+s/LaTeX/\\LaTeX{}/g
+s/@file/\\textit/g
+s/@strong/\\textbf/g
+s/[w]{/mbox{/g
+
+## Quote some special characters.
+s/%/\\%/g
+s/_/\\_/g
+
+## Adapt to how a man-page is typeset.
+## En-dashes in front of long options really suck!
+s/--/-\\nolig*-/g
+
+## Converting the at-signs to backslashes is a bit tricky.
+s/^@item/\\item/
+s/@\([A-Za-z][A-Za-z]*\){/\\\1{/g
+s/@@/@/g
+
+## Convert selected macro names.
+s/\\jobname/\\textbackslash jobname/g
+
+## Make qualified Perl names breakable.
+s/::/::\\discretionary{}{}{}/g
+%</teximan2latex>
+% \fi
+%
+%
+%
+% \iffalse
+%<*typog-grep>
+#! /usr/bin/env perl
+
+
+use autodie qw(:all);
+use strict;
+use warnings;
+
+use Data::Dumper ();
+use English;
+use File::Basename ();
+use Getopt::Long;
+use IO::File;
+use IO::Handle;
+use Term::ANSIColor ();
+
+
+use constant COMMAND_NAME => File::Basename::basename($PROGRAM_NAME);
+
+
+my $DEBUG = 0;
+my $MATCH_COUNT = 0;
+my $OUTPUT_IS_REDIRECTED;
+
+
+sub fail_with_error {
+ print STDERR join('', COMMAND_NAME, ': ', @_, "\n");
+ exit 2;
+}
+
+
+sub issue_warning {
+ print STDERR join('', COMMAND_NAME, ': warning: ', @_, "\n");
+}
+
+
+sub debug_print {
+ return unless $DEBUG;
+ print STDERR "+ @_\n";
+}
+
+
+sub quote_filesystem {qq("$_[0]")}
+sub quote_literal {qq(`$_[0]')}
+
+
+sub limit_string_length {
+ my ($a_string, $a_maximum_length) = @_;
+
+ if (length $a_string <= $a_maximum_length) {
+ $a_string;
+ } else {
+ substr($a_string, 0, $a_maximum_length - 3) . '...';
+ }
+}
+
+
+## We set all colors to `undef' and fill them later with the values
+## of the actual configuration.
+my $highlight_patterns = {
+ PARTIAL_LINE => {
+ FONT_SPEC => [qr#
+ \\
+ (?: OMS | OMX | OT1 | T1 | TS1 | U )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ #x, undef],
+ MATH => [qr#
+ \$
+ \\
+ (?: LMS | OML )
+ (?: /[^/]+ ){5} / \S+ \s
+ (?: \([+-]\d+\) )?
+ .*?
+ \$
+ #x, undef]
+ },
+ WHOLE_LINE => {
+ FILL_STATE => [qr#^(?:Under|Over)full \\hbox .*$#, undef],
+ FIRST_VBOX => [qr#^%%#, undef],
+ HORIZONTAL_BREAKPOINT => [qr#^@@\d+:.*$#, undef],
+ HORIZONTAL_BREAK_CANDIDATE => [qr#^@[\\ ].*$#, undef],
+ LINE_BREAK_PASS => [qr#^@[a-z]+?pass#, undef],
+ TIGHTNESS => [qr#^(?:Loose|Tight) \\hbox .*$#, undef],
+ VERTICAL_BREAKPOINT => [qr#^% t=\d+.*$#, undef]
+ }
+};
+
+
+sub colorize_line {
+ my ($configuration, $line) = @_;
+
+ foreach my $pattern_color_pair (values %{$highlight_patterns->{WHOLE_LINE}}) {
+ next unless $pattern_color_pair->[1];
+ return Term::ANSIColor::colored($line, $pattern_color_pair->[1])
+ if $line =~ $pattern_color_pair->[0];
+ }
+ return $line if $line =~ m#^\.#; # we do not paint box contents yet
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{MATH}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{MATH}->[1])
+ #egx;
+
+ $line =~ s#$highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[0]
+ #Term::ANSIColor::colored($MATCH, $highlight_patterns->{PARTIAL_LINE}->{FONT_SPEC}->[1])
+ #egx;
+
+ return $line;
+}
+
+
+my $open_or_close_tag_regexp = qr#^</?typog-inspect[ >]#; # somewhat sloppy definition
+my $close_tag_regexp = qr#^</typog-inspect>#;
+my $open_tag_regexp =
+ qr#^
+ <typog-inspect \s+
+ id="(?<id_match> .*?)" \s+
+ job="(?<job_match> .*?)" \s+
+ line="(?<line_match> .*?)" \s+
+ page="(?<page_match> .*?)"
+ >#x;
+
+
+sub grep_log_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $job_name;
+ my $line_number = 0; # line number in the log file we are inspecting, i.e., $filename
+ my $match_count = 0;
+ my $source_line_number; # line number in TeX file the log refers to, i.e., "$job_name.tex"
+ my $page_number;
+ my $regexp_modifier = $options->{IGNORE_CASE} ? 'i' : '';
+ my $id_value;
+ my @nesting_levels;
+
+ if ($options->{WORD_REGEXP}) {
+ $id_regexp = "\\b$id_regexp\\b";
+ }
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if (@nesting_levels and $nesting_levels[-1] and $line !~ $open_or_close_tag_regexp) {
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ if ($options->{ID} and not $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_INLINE_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id = Term::ANSIColor::colored($formatted_id ,
+ $configuration->{COLORS}->{ID_COLOR});
+ }
+ print $formatted_id, ' ';
+ }
+
+ if ($options->{COLORIZE_OUTPUT}) {
+ print colorize_line($configuration, $line);
+ } else {
+ print $line;
+ }
+ print "\n";
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ $job_name = $+{job_match};
+ $source_line_number = $+{line_match};
+ $page_number = $+{page_match};
+
+ my $found_matching_id = ($id_value =~ m/(?$regexp_modifier)$id_regexp/) ? 1 : 0;
+ push @nesting_levels, $found_matching_id;
+ if ($found_matching_id) {
+ ++$MATCH_COUNT; # global count -- needed for return code of program
+ ++$match_count; # per file count -- needed to be able to separate the hunks
+
+ print "\n" if $match_count >= 2;
+ if ($options->{ID} and $configuration->{PRINT_ID_AS_HEADING}) {
+ my $formatted_id = sprintf $configuration->{ID_HEADING_FORMAT}, $id_value;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_id =
+ Term::ANSIColor::colored($formatted_id,
+ $configuration->{COLORS}->{ID_HEADING_COLOR});
+ }
+ print $formatted_id, "\n";
+ }
+ }
+ }
+ }
+}
+
+
+sub show_ids_in_file {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ my $line_number = 0;
+ my @nesting_levels;
+
+ while (my $line = readline $file) {
+ chomp $line;
+ $line_number++;
+
+ if ($line =~ $close_tag_regexp) {
+ fail_with_error("$filename: $line_number: mismatched open/close tags") unless @nesting_levels;
+ pop @nesting_levels;
+ }
+
+ if ($line =~ $open_tag_regexp) {
+ my $id_value = limit_string_length($+{id_match}, $configuration->{ID_MAX_LENGTH});
+ my $job_name = $+{job_match};
+ my $source_line_number = $+{line_match};
+ my $page_number = $+{page_match};
+
+ ++$MATCH_COUNT;
+ push @nesting_levels, 1;
+
+ if ($options->{LOG_LINE_NUMBER}) {
+ my $formatted_log_line_number =
+ sprintf $configuration->{LOG_LINE_NUMBER_FORMAT}, $line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_log_line_number =
+ Term::ANSIColor::colored($formatted_log_line_number,
+ $configuration->{COLORS}->{LOG_LINE_NUMBER});
+ }
+ print $formatted_log_line_number, ' ';
+ }
+
+ print "$job_name: " if $options->{JOB_NAME};
+
+ if ($options->{LINE_NUMBER}) {
+ my $formatted_line_number = sprintf $configuration->{LINE_NUMBER_FORMAT}, $source_line_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_line_number =
+ Term::ANSIColor::colored($formatted_line_number,
+ $configuration->{COLORS}->{LINE_NUMBER});
+ }
+ print $formatted_line_number, ' ';
+ }
+
+ if ($options->{PAGE_NUMBER}) {
+ my $formatted_page_number = sprintf $configuration->{PAGE_NUMBER_FORMAT}, $page_number;
+ if ($options->{COLORIZE_OUTPUT}) {
+ $formatted_page_number =
+ Term::ANSIColor::colored($formatted_page_number,
+ $configuration->{COLORS}->{PAGE_NUMBER});
+ }
+ print $formatted_page_number, ' ';
+ }
+
+ my $indent = $configuration->{ID_INDENT} * (@nesting_levels - 1);
+ print ' ' x $indent, $id_value, "\n";
+ }
+ }
+}
+
+
+sub open_file_for_reading {
+ my $filename = shift;
+
+ my $file;
+
+ if ($filename eq 'stdin') {
+ $file = IO::Handle->new();
+ $file->fdopen(fileno(STDIN), 'r') or
+ fail_with_error("cannot open stdin: $OS_ERROR");
+ } else {
+ $file = IO::File->new($filename, 'r') or
+ fail_with_error("cannot open @{[quote_filesystem($filename)]}: $OS_ERROR");
+ }
+
+ $file;
+}
+
+
+sub close_file {
+ my ($file, $filename) = shift;
+
+ $file->close or
+ issue_warning("problems while closing @{[quote_filesystem($filename)]}: $OS_ERROR");
+}
+
+
+sub grep_or_show {
+ my ($options, $configuration, $file, $filename, $id_regexp) = @_;
+
+ if ($options->{SHOW_ALL_IDS}) {
+ show_ids_in_file($options, $configuration, $file, $filename, $id_regexp);
+ } else {
+ grep_log_file($options, $configuration, $file, $filename, $id_regexp);
+ }
+}
+
+
+sub scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ if (@$log_filenames) {
+ foreach my $log_filename (@$log_filenames) {
+ $log_filename = 'stdin' if $log_filename eq '-';
+ if (@$log_filenames >= 2) {
+ print "\n" unless $log_filename eq $log_filenames->[0];
+ my $filename_header = "==> $log_filename <==\n";
+ $filename_header = Term::ANSIColor::colored($filename_header,
+ $configuration->{COLORS}->{FILE_HEADER})
+ if $options->{COLORIZE_OUTPUT};
+ print $filename_header;
+ }
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+ } else {
+ my $log_filename = 'stdin';
+ my $file = open_file_for_reading($log_filename);
+ grep_or_show($options, $configuration, $file, $log_filename, $id_regexp);
+ close_file($file, $log_filename);
+ }
+}
+
+
+sub redirect_and_scan_files {
+ my ($options, $configuration, $id_regexp, $log_filenames) = @_;
+
+ my $pager;
+
+ my $pid = open($pager, '|-', $configuration->{PAGER}, $configuration->{PAGER_FLAGS});
+ fail_with_error('failed to redirect to pager ', quote_literal($configuration->{PAGER}),
+ ' with flags ', quote_literal($configuration->{PAGER_FLAGS}),
+ ": $OS_ERROR")
+ unless defined $pid;
+ my $stdout = select $pager;
+
+ $pager->autoflush;
+ scan_files($options, $configuration, $id_regexp, $log_filenames);
+
+ close $pager or issue_warning "error occurred while closing the pager (pid: $pid) pipe: $OS_ERROR";
+ select $stdout;
+}
+
+
+########################################################################
+
+
+my $configuration_key_map = {
+ 'id-format' => 'ID_INLINE_FORMAT',
+ 'id-indent' => 'ID_INDENT',
+ 'id-heading' => 'PRINT_ID_AS_HEADING',
+ 'id-heading-format' => 'ID_HEADING_FORMAT',
+ 'id-max-length' => 'ID_MAX_LENGTH',
+ 'line-number-format' => 'LINE_NUMBER_FORMAT',
+ 'log-line-number-format' => 'LOG_LINE_NUMBER_FORMAT',
+ 'page-number-format' => 'PAGE_NUMBER_FORMAT',
+
+ 'file-header-color' => 'FILE_HEADER',
+ 'fill-state-color' => 'FILL_STATE',
+ 'first-vbox-color' => 'FIRST_VBOX',
+ 'font-spec-color' => 'FONT_SPEC',
+ 'horizontal-break-candidate-color' => 'HORIZONTAL_BREAK_CANDIDATE',
+ 'horizontal-breakpoint-color' => 'HORIZONTAL_BREAKPOINT',
+ 'id-color' => 'ID_COLOR',
+ 'id-heading-color' => 'ID_HEADING_COLOR',
+ 'line-break-pass-color' => 'LINE_BREAK_PASS',
+ 'line-number-color' => 'LINE_NUMBER',
+ 'log-line-number-color' => 'LOG_LINE_NUMBER',
+ 'math-color' => 'MATH',
+ 'page-number-color' => 'PAGE_NUMBER',
+ 'pager' => 'PAGER',
+ 'pager-flags' => 'PAGER_FLAGS',
+ 'tightness-color' => 'TIGHTNESS',
+ 'vertical-breakpoint-color' => 'VERTICAL_BREAKPOINT'
+};
+
+
+my $default_configuration = {
+ COLORS => {
+ FILE_HEADER => 'bold black',
+ FILL_STATE => 'bold magenta',
+ FIRST_VBOX => 'bold red',
+ FONT_SPEC => 'grey12',
+ HORIZONTAL_BREAKPOINT => 'bold green',
+ HORIZONTAL_BREAK_CANDIDATE => 'blue',
+ ID_COLOR => 'white on_black',
+ ID_HEADING_COLOR => 'white on_black',
+ LINE_BREAK_PASS => 'bold green',
+ LINE_NUMBER => 'bold black',
+ LOG_LINE_NUMBER => 'italic black',
+ MATH => 'yellow',
+ PAGE_NUMBER => 'bold white on_red',
+ TIGHTNESS => 'bold cyan',
+ VERTICAL_BREAKPOINT => 'red'
+ },
+ ID_INLINE_FORMAT => '%s:',
+ ID_HEADING_FORMAT => '--> %s <--',
+ ID_INDENT => 8,
+ ID_MAX_LENGTH => 40,
+ LINE_NUMBER_FORMAT => '%5d',
+ LOG_LINE_NUMBER_FORMAT => '%6d',
+ PAGE_NUMBER_FORMAT => '[%3d]',
+ PAGER => 'less',
+ PAGER_FLAGS => '--quit-if-one-screen',
+ PRINT_ID_AS_HEADING => 0
+};
+
+
+sub initialize_highlighting_from_configuration {
+ my $configuration = shift;
+
+ while (my (undef, $assoc) = each %$highlight_patterns) {
+ while (my ($name, $pattern_color_pair) = each %$assoc) {
+ $pattern_color_pair->[1] = $configuration->{COLORS}->{$name};
+ }
+ }
+}
+
+
+sub modify_configuration {
+ my ($configuration, $key, $value) = @_;
+
+ fail_with_error('malformed KEY=VALUE pair -- missing key') unless $key;
+
+ if (defined $configuration_key_map->{$key}) {
+ if ($key =~ m/-color$/) {
+ $configuration->{COLORS}->{$configuration_key_map->{$key}} = $value;
+ } else {
+ $configuration->{$configuration_key_map->{$key}} = $value;
+ }
+ } else {
+ fail_with_error("@{[quote_literal($key)]} is not a valid configuration KEY");
+ }
+}
+
+
+sub setup_configuation {
+ my ($config_spec, $configuration) = @_;
+
+ foreach my $spec (split ':', $config_spec) {
+ my ($key, $value) = split '=', $spec;
+ modify_configuration($configuration, $key, $value);
+ }
+}
+
+
+my $default_options = {
+ COLORIZE_MODE => 'auto',
+ DEBUG => 0,
+ ID => 0,
+ IGNORE_CASE => 0,
+ JOB_NAME => 0,
+ LINE_NUMBER => 0,
+ LOG_LINE_NUMBER => 0,
+ PAGE_NUMBER => 0,
+ REQUEST_PAGER => 1,
+ WORD_REGEXP => 0
+};
+
+
+sub show_help {
+ print <<HELP_TEXT;
+Usage: @{[COMMAND_NAME]} [OPTION] ID-REGEXP LOG-FILE...
+Structured grep for typog-inspect elements that match ID-REGEXP in LOG-FILE.
+
+Options
+ --color [WHEN],
+ --colour [WHEN] use color to highlight specific log contents
+ WHEN is 'always', 'never', or 'auto'
+ -C, --config KEY=VALUE set configuration KEY to VALUE
+ -i, --[no-]id print matching id with output lines
+ -y, --[no-]ignore-case ignore case distinctions in patterns and data
+ -j, --[no-]job-name print \\jobname with output lines
+ -n, --[no-]line-number print TeX-source line number with output lines
+ -N, --[no-]log-line-number print log-file line number with output lines
+ -p, --[no-]page-number print page number with output lines
+ -P, --[no-]pager redirect output to pager
+ -w, --[no-]word-regexp match only whole words
+
+ -a, --all, --any show all IDs in LOG-FILE
+ --debug turn on debug output
+ -h, --help display this help and exit
+ --show-config show default configuration and exit
+ -V, --version show version information and exit
+
+HELP_TEXT
+
+ exit 0;
+}
+
+
+sub show_configuration {
+ my $format_string_value = sub {quote_literal($default_configuration->{$_[0]})};
+
+ print <<FIXED_CONFIGURATION_TEXT;
+Configuration
+Key Default Value
+------------------------------------ -------------
+id-format @{[$format_string_value->('ID_INLINE_FORMAT')]}
+id-heading $default_configuration->{PRINT_ID_AS_HEADING}
+id-heading-format @{[$format_string_value->('ID_HEADING_FORMAT')]}
+id-indent $default_configuration->{ID_INDENT}
+id-max-length $default_configuration->{ID_MAX_LENGTH}
+line-number-format @{[$format_string_value->('LINE_NUMBER_FORMAT')]}
+log-line-number-format @{[$format_string_value->('LOG_LINE_NUMBER_FORMAT')]}
+page-number-format @{[$format_string_value->('PAGE_NUMBER_FORMAT')]}
+pager @{[$format_string_value->('PAGER')]}
+pager-flags @{[$format_string_value->('PAGER_FLAGS')]}
+
+FIXED_CONFIGURATION_TEXT
+
+ foreach my $configuration_key (sort keys %$configuration_key_map) {
+ next unless $configuration_key =~ m/-color$/;
+ printf("%-36s %s\n",
+ $configuration_key,
+ quote_literal($default_configuration->
+ {COLORS}->
+ {$configuration_key_map->{$configuration_key}}));
+ }
+
+ exit 0;
+}
+
+
+sub show_version {
+ print <<VERSION_TEXT;
+typog-grep 0.1
+
+Copyright (C) 2024 by Ch. L. Spiel
+License LPPL: LaTeX Project Public License version 1.3 or later
+VERSION_TEXT
+
+ exit 0;
+}
+
+
+sub get_options {
+ my ($options, $configuration) = @_;
+
+ Getopt::Long::Configure('gnu_getopt', 'no_ignore_case');
+
+ Getopt::Long::GetOptions('a|all|any' => \$options->{SHOW_ALL_IDS},
+ 'color|colour=s' => \$options->{COLORIZE_MODE},
+ 'C|configuration=s' => sub{setup_configuation($_[1], $configuration)},
+ 'debug+' => \$DEBUG,
+ 'h|help' => \&show_help,
+ 'i|id!' => \$options->{ID},
+ 'y|ignore-case!' => \$options->{IGNORE_CASE},
+ 'j|job-name!' => \$options->{JOB_NAME},
+ 'n|line-number!' => \$options->{LINE_NUMBER},
+ 'N|log-line-number!' => \$options->{LOG_LINE_NUMBER},
+ 'p|page-number!' => \$options->{PAGE_NUMBER},
+ 'P|pager!' => \$options->{REQUEST_PAGER},
+ 'show-config' => \&show_configuration,
+ 'V|version' => \&show_version,
+ 'w|word-regexp!' => \$options->{WORD_REGEXP}) or
+ fail_with_error('problems while parsing options');
+
+ fail_with_error("unknown colorize mode @{[quote_literal($options->{COLORIZE_MODE})]}")
+ unless $options->{COLORIZE_MODE} =~ m/^(?:always|auto|never)$/i
+}
+
+
+sub do_colorize {
+ my $colorize_mode = shift;
+
+ if ($colorize_mode =~ m/never/i) {
+ 0;
+ } elsif ($colorize_mode =~ m/always/i) {
+ 1;
+ } elsif ($colorize_mode =~ m/auto/i) {
+ not $OUTPUT_IS_REDIRECTED;
+ }
+}
+
+
+## For the comparison with the POSIX spec of grep(1) consult
+## https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html
+
+
+sub main {
+ $OUTPUT_IS_REDIRECTED = -t STDOUT ? 0 : 1;
+
+ my $options = {%$default_options};
+ my $configuration = {%$default_configuration};
+
+ get_options($options, $configuration);
+ $options->{COLORIZE_OUTPUT} = do_colorize($options->{COLORIZE_MODE});
+ initialize_highlighting_from_configuration($configuration);
+ debug_print(Data::Dumper::Dumper($configuration));
+ debug_print(Data::Dumper::Dumper($options));
+
+ my $id_regexp;
+ if ($options->{SHOW_ALL_IDS}) {
+ $id_regexp = '^';
+ issue_warning("option @{[quote_literal('--id')]} ignored in @{[quote_literal('--all')]} mode")
+ if $options->{ID};
+ } else {
+ fail_with_error('missing ID-REGEXP') unless @ARGV >= 1;
+ $id_regexp = shift @ARGV;
+ }
+
+ if ($options->{REQUEST_PAGER} && $OUTPUT_IS_REDIRECTED) {
+ issue_warning("option @{[quote_literal('--pager')]} ignored because output is redirected");
+ }
+ my $use_pager = $options->{REQUEST_PAGER} && !$OUTPUT_IS_REDIRECTED;
+ if ($use_pager) {
+ redirect_and_scan_files($options, $configuration, $id_regexp, \@ARGV);
+ } else {
+ scan_files($options, $configuration, $id_regexp, \@ARGV);
+ }
+
+ exit ($MATCH_COUNT == 0);
+}
+
+
+main();
+%</typog-grep>
+% \fi
+%
+%
+%
+% \iffalse
+%<*typog-grep-documentation>
+=begin man
+
+.\" Turn off justification.
+.na
+
+=end man
+
+=head1 NAME
+
+typog-grep - grep for typog-inspect elements in LaTeX log files
+
+
+=head1 SYNOPSIS
+
+=over
+
+=item B<typog-grep> -a|--all|--any [I<OPTION>...] F<LOG-FILE>...
+
+=item B<typog-grep> [I<OPTION>...] I<REGEXP> F<LOG-FILE>...
+
+=back
+
+The first form shows all C<E<lt>typog-inspect id="I<ID>" ...E<gt>> elements in F<LOG-FILE>.
+
+The second form shows the contents of C<E<lt>typog-inspect id="I<ID>" ...E<gt>> elements
+whose I<ID>s match I<REGEXP> in F<LOG-FILE>.
+
+If no F<LOG-FILE> is given read from F<stdin>.
+The S<filename C<->> is synonymous to F<stdin>.
+
+
+=head1 DESCRIPTION
+
+B<typog-grep> is a tailored post-processor for LaTeX log files
+and the C<typoginspect> environment as provided by S<package typog>.
+It shares more with the venerable
+L<B<sgrep>|https://www.cs.helsinki.fi/u/jjaakkol/sgrep.html>
+than with S<POSIX L<B<grep>|https://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html>>.
+
+The LaTeX user brackets her text in
+
+ \begin{typoginspect}{ID}
+ Text and code to investigate
+ \end{typoginspect}
+
+where I<ID> is used to identify one or more bracketed snippets.
+I<ID> does not have to be unique.
+The I<REGEXP> mechanism makes it easy to select groups of related I<ID>s
+if they are named accordingly.
+
+In F<LOG-FILE> the environment shows up, packed with tracing information, as
+
+=begin texinfo
+
+@display
+@relax
+
+=end texinfo
+
+ <typog-inspect id="ID" job="JOB-NAME" line="LINE-NUMBER" page="PAGE-NUMBER">
+ Trace Data
+ </typog-inspect>
+
+=begin texinfo
+
+@end display
+@relax
+
+=end texinfo
+
+where all the capital-letter sequences are meta-variables
+and in particular
+I<JOB-NAME> is the expansion of C<\jobname>,
+I<LINE-NUMBER> is the LaTeX source file line number
+of the beginning of the C<typoginspect> environment,
+and I<PAGE-NUMBER> is the page where
+the output of S<C<Text and code to investigate>> occurs.
+
+B<typog-grep> reveals the contents of F<LOG-FILE>
+between C<E<lt>typog-inspect id="I<ID>" ...E<gt>>
+and C<E<lt>/typog-inspectE<gt>> excluding the XML-tags.
+Access the I<JOB-NAME>, I<LINE-NUMBER>, and I<PAGE-NUMBER>
+with the commandline options
+B<--job-name>, B<--line-number>, and B<--page-number>, respectively.
+Use B<--id> to show the name of the IDs that matched I<REGEXP>.
+
+C<typoginspect> environments can be nested.
+B<typog-grep> respects the nesting,
+i.e., if the I<ID> of the nested environment does not match I<REGEXP>
+it will not be included in the program's output.
+
+
+=head1 OPTIONS
+
+The list of options is sorted by the names of the long options.
+
+=over 4
+
+=item B<-a>, B<--all>, B<--any>
+
+ID-discovery mode:
+Show all C<typog-inspect> elements independent of any matching patterns.
+
+=item B<--color>, B<colour> I<WHEN>
+
+Colorize specific log contents for the matching ids.
+The S<argument I<WHEN>> determines when to apply color:
+C<always>, C<never>, S<or C<auto>>.
+The setting C<auto> checks whether standard output has been redirected.
+This is the default.
+
+=item B<-C>, B<--config> I<KEY>=I<VALUE>[:I<KEY>=I<VALUE>[:...]]
+
+Set one or more configuration I<KEY> to I<VALUE> pairs.
+See S<Sec. CONFIGURATION> below for a description of all available configuration items.
+Use option B<--show-config> to display the default configuration.
+
+=item B<--debug>
+
+Turn on debug output on F<stderr>.
+
+=item B<-h>, B<--help>
+
+Display brief help then exit.
+
+=item B<-i>, B<--[no-]id>
+
+Print the actual id name that matched I<REGEXP>.
+Control the appearance of the matching id with configuration S<item C<id-heading>>.
+
+=item B<-y>, B<--[no-]ignore-case>
+
+Match ids while ignoring case distinctions in patterns and data.
+
+=item B<-j>, B<--[no-]job-name>
+
+Print the C<\jobname> that B<tex> associated with the input file.
+
+=item B<-n>, B<--[no-]line-number>
+
+Print the line number where the S<C<typoginspect> environment>
+was encountered in the LaTeX source file.
+
+=item B<-N>, B<--[no-]log-line-number>
+
+Print the line number of the F<log>-file where the current line was encountered.
+
+=item B<-p>, B<--[no-]page-number>
+
+Print page number where the contents of the S<C<typoginspect> environment>
+starts in the typeset document.
+
+=item B<-P>, B<--[no-]pager>
+
+Redirect output from F<stdout> to the configured pager.
+
+=item B<--show-config>
+
+Show the default configuration and exit.
+
+=item B<-V>, B<--version>
+
+Show version information and exit.
+
+=item B<-w>, B<--[no-]word-regexp>
+
+Match only whole words.
+
+=back
+
+
+=head1 CONFIGURATION
+
+=over 4
+
+=item C<id-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing matching ids in inline-mode,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%s:>.>
+
+=item C<id-heading>=C<0>E<verbar>C<1>
+
+Choose between printing the matching ids with S<option B<--id>>:
+S<Inline (C<0>)> or heading before the matching data (C<1>).
+S<Default: C<0>.>
+
+=item C<id-heading-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing matching ids in heading-mode,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<--E<gt> %s E<lt>-->.>
+
+=item C<id-indent>=I<INDENT>
+
+Indentation of nested typog-inspect tags.
+Only used in ``discovery'' mode (first form), i.e., if B<--all> is active.
+S<Default: 8.>
+
+=item C<id-max-length>=I<MAXIMUM-LENGTH>
+
+Set the maximum length of a matching id for printing.
+It a matching id exceeds this length it will be truncated
+and the last three characters (short of I<MAXIMUM-LENGTH>) will be replaced by dots.
+S<Default: 40.>
+
+=item C<line-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing TeX source line numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%5d>.>
+
+=item C<log-line-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing log line numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<%6d>.>
+
+=item C<page-number-format>=I<FORMAT>
+
+Control the I<FORMAT> for printing page numbers,
+where I<FORMAT> is passed to Perl's C<printf>.
+S<Default: C<[%3d]>.>
+
+=item C<pager>=I<PAGER>
+
+Name of pager application to pipe output into
+if run with S<option B<--pager>>.
+S<Default: C<less>>.
+
+=item C<pager-flags>=I<FLAGS>
+
+Pass I<FLAGS> to I<PAGER>.
+S<Default: C<--quit-if-one-screen>>.
+
+=item Color Configuration
+
+For the syntax of the color specifications consult
+the manual page of Term::ANSIColor(pm).
+
+=over 4
+
+=item C<file-header-color>
+
+Color of the filename header.
+
+=item C<fill-state-color>
+
+Color of the messages that report ``Underfull hbox'' or ``Overfull hbox''.
+
+=item C<first-vbox-color>
+
+Color of the first vbox on a page.
+
+=item C<font-spec-color>
+
+Color of font specifications.
+
+=item C<horizontal-break-candidate-color>
+
+Color of lines with horizontal-breakpoint S<candidates C<@>>.
+
+=item C<horizontal-breakpoint-color>
+
+Color of lines with horizontal S<breakpoints C<@@>>.
+
+=item C<id-color>
+
+Color of matching ids when printed inline.
+
+=item C<id-heading-color>
+
+Color of matching ids when printed in heading form.
+
+=item C<line-break-pass-color>
+
+Color of the lines showing which pass (e.g., C<@firstpass>)
+of the line-breaking algorithm is active.
+
+=item C<line-number-color>
+
+Color of TeX-source-file line numbers.
+
+=item C<log-line-number-color>
+
+Color of log-file line numbers.
+
+=item C<math-color>
+
+Color used for math expressions including their font specs.
+
+=item C<page-number-color>
+
+Color of page numbers of the final output.
+
+=item C<tightness-color>
+
+Color of lines with Tight/Loose hbox reports.
+
+=item C<vertical-breakpoint-color>
+
+Color of possible vertical breakpoints.
+
+=back
+
+=back
+
+
+=head2 Brief summary of colors and attributes
+
+=over 4
+
+=item Foreground Color
+
+C<black>, C<red>, C<green>, C<yellow>,
+C<blue>, C<magenta>, C<cyan>, C<white>,
+
+Prefix with C<bright_> for high-intensity or bold foreground.
+
+=item Foreground Grey
+
+C<grey0>, ..., C<grey23>
+
+=item Background Color
+
+C<on_black>, C<on_red>, C<on_green>, C<on_yellow>,
+S<C<on_blue>>, S<C<on_magenta>>, S<C<on_cyan>>, S<C<on_white>>
+
+Replace C<on_> with C<on_bright_> for high-intensity or bold background.
+
+=item Background Grey
+
+C<on_grey0>, ..., C<on_grey23>
+
+=item Text Attribute
+
+C<bold>, C<dark>, C<italic>, C<underline>, C<reverse>
+
+=back
+
+
+=head1 EXIT STATUS
+
+The exit status is 0 if at least one I<ID> matched I<REGEXP>,
+1 if no I<ID> matched I<REGEXP>, and 2 if an error occurred.
+
+
+=head1 SEE ALSO
+
+B<grep>(1), B<printf>(3), B<Term::ANSIColor>(pm)
+
+
+=cut
+%</typog-grep-documentation>
+% \fi
+%
+%
+%
+\endinput
+%
+%
+%
+%%% Local Variables:
+%%% compile-command: "latex typog.dtx"
+%%% fill-column: 96
+%%% End:
diff --git a/Master/texmf-dist/source/latex/typog/typog.ins b/Master/texmf-dist/source/latex/typog/typog.ins
new file mode 100644
index 00000000000..06378d86bbe
--- /dev/null
+++ b/Master/texmf-dist/source/latex/typog/typog.ins
@@ -0,0 +1,74 @@
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+
+
+\input docstrip
+
+
+\keepsilent
+\askforoverwritefalse
+
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2024 by Ch. L. Spiel
+
+This work may be distributed and/or modified under the conditions
+of the LaTeX Project Public License, either version 1.3 of this
+license or (at your option) any later version. The latest version
+of this license is in
+ http://www.latex-project.org/lppl.txt
+and version 1.3 or later is part of all distributions of LaTeX
+version 2003/12/01 or later.
+
+This work has the LPPL maintenance status `maintained'.
+
+The Current Maintainer of this work is Ch. L. Spiel.
+
+This work consists of the files typog.dtx and typog.ins
+and the derived files typog.sty, slant-angle.mp,
+crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+typog-example.tex, typog-nomt.tex, typog-grep.pl,
+typog-grep.pod, and teximan2latex.sed.
+
+
+\endpreamble
+
+
+\edef\source{\jobname.dtx}
+
+\generate{\file{typog.sty}{\from{\source}{package}}
+ \file{typog-example.tex}{\from{\source}{example}}
+ \file{typog-nomt.tex}{\from{\source}{nomicrotype}}
+ \file{typog.ist}{\from{\source}{index-style}}}
+
+
+\nopostamble
+\generate{\file{title.mp}{\from{\source}{title}}
+ \file{slant-angle.mp}{\from{\source}{slantangle}}
+ \file{crooked-paragraphs.mp}{\from{\source}{crookedparagraphs}}
+ \file{smooth-parshapes.mp}{\from{\source}{smoothparshapes}}}
+
+
+\nopreamble
+\generate{\file{teximan2latex.sed}{\from{\source}{teximan2latex}}
+ \file{typog-grep.pl}{\from{\source}{typog-grep}}
+ \file{typog-grep.pod}{\from{\source}{typog-grep-documentation}}}
+
+
+\endbatchfile
+
+
+%% Local Variables:
+%% compile-command: "latex typog.ins"
+%% mode: latex
+%% End:
diff --git a/Master/texmf-dist/tex/latex/typog/typog.sty b/Master/texmf-dist/tex/latex/typog/typog.sty
new file mode 100644
index 00000000000..bbb03cb5cbe
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/typog/typog.sty
@@ -0,0 +1,1401 @@
+%%
+%% This is file `typog.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% typog.dtx (with options: `package')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2024 by Ch. L. Spiel
+%%
+%% This work may be distributed and/or modified under the conditions
+%% of the LaTeX Project Public License, either version 1.3 of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3 or later is part of all distributions of LaTeX
+%% version 2003/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Ch. L. Spiel.
+%%
+%% This work consists of the files typog.dtx and typog.ins
+%% and the derived files typog.sty, slant-angle.mp,
+%% crooked-paragraphs.mp, smooth-parshapes.mp, title.mp,
+%% typog-example.tex, typog-nomt.tex, typog-grep.pl,
+%% typog-grep.pod, and teximan2latex.sed.
+%%
+%%
+\NeedsTeXFormat{LaTeX2e}[2005/12/01]
+\ProvidesPackage{typog}
+ [2024/05/07 v0.3 TypoGraphic extensions]
+
+\RequirePackage{etoolbox}
+\RequirePackage{everyhook}
+\RequirePackage{xkeyval}
+
+\newcommand*{\typog@TYPOG}{}
+\newcommand*{\typoglogo}{\textsf{T\itcorr*{-5}\textsl{y}poG}}
+\newif\iftypog@debug
+\newcommand*{\typog@typeout}[1]
+ {\iftypog@debug
+ \typeout{typog: #1}%
+ \fi}
+
+\ExplSyntaxOn
+\let\typog@trim@spaces=\tl_trim_spaces:o
+\ExplSyntaxOff
+
+\newcommand{\typog@register@pdfsubstitute}[1]{%
+ \AtBeginDocument{%
+ \ifdefined\pdfstringdefDisableCommands
+ \pdfstringdefDisableCommands{#1}%
+ \fi}}
+
+\newif\iftypog@microtype@preloaded
+
+\ifdefined\MT@MT
+ \typog@typeout{package microtype preloaded}%
+ \typog@microtype@preloadedtrue
+ \def\typog@require@preloaded@microtype{\relax}
+\else
+ \typog@microtype@preloadedfalse
+ \def\typog@require@preloaded@microtype
+ {\PackageError{typog}%
+ {package microtype not (pre-)loaded}%
+ {package microtype must be loaded before package typog}}
+\fi
+
+\newif\iftypog@microtype@loaded
+
+\AtBeginDocument{
+ \ifdefined\MT@MT
+ \typog@typeout{package microtype loaded}%
+ \typog@microtype@loadedtrue
+ \def\typog@require@microtype{\relax}
+ \else
+ \typog@microtype@loadedfalse
+ \def\typog@require@microtype
+ {\PackageError{typog}%
+ {package microtype not loaded}%
+ {require package microtype before package typog}}%
+ \fi
+}
+
+\newmuskip\typog@mathitalicscorrection
+\newlength{\typog@textitalicscorrection}
+\newlength{\typog@ligaturekern}
+\newlength{\typog@raisecapitaldash}
+\newlength{\typog@raisecapitalguillemets}
+\newlength{\typog@raisecapitalhyphen}
+\newlength{\typog@raisecapitaltimes}
+\newlength{\typog@raiseguillemets}
+\newlength{\typog@raisefiguredash}
+\newlength{\typog@slashkern}
+\newcommand*{\typog@breakpenalty}{\exhyphenpenalty}
+\newlength{\typog@dim@unit}
+\setlength{\typog@dim@unit}{.001em}
+\newcommand*{\typog@trackingttspacing}{300, 90, 60}
+\newcommand*{\typog@default@shrink@i}{5}
+\newcommand*{\typog@default@shrink@ii}{10}
+\newcommand*{\typog@default@shrink@iii}{20}
+\newcommand*{\typog@shrink@i}{}
+\newcommand*{\typog@shrink@ii}{}
+\newcommand*{\typog@shrink@iii}{}
+\newcommand*{\typog@default@stretch@i}{5}
+\newcommand*{\typog@default@stretch@ii}{10}
+\newcommand*{\typog@default@stretch@iii}{20}
+\newcommand*{\typog@stretch@i}{}
+\newcommand*{\typog@stretch@ii}{}
+\newcommand*{\typog@stretch@iii}{}
+
+\def\typog@one@of@three#1,#2,#3\relax{\typog@trim@spaces{#1}}
+\def\typog@two@of@three#1,#2,#3\relax{\typog@trim@spaces{#2}}
+\def\typog@three@of@three#1,#2,#3\relax{\typog@trim@spaces{#3}}
+
+\newcommand*{\typog@triple@get@i}[1]{\expandafter\typog@one@of@three #1\relax}
+\newcommand*{\typog@triple@get@ii}[1]{\expandafter\typog@two@of@three #1\relax}
+\newcommand*{\typog@triple@get@iii}[1]{\expandafter\typog@three@of@three #1\relax}
+
+\newcommand*{\typog@set@shrink@limits}
+ {\edef\typog@@star{*}%
+ \edef\typog@@limit{\typog@triple@get@i{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@i{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@ii{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@ii{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@iii{\typog@shrinklimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@shrink@iii{\number\typog@@limit}\fi}
+
+\newcommand*{\typog@set@stretch@limits}
+ {\edef\typog@@star{*}%
+ \edef\typog@@limit{\typog@triple@get@i{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@i{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@ii{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@ii{\number\typog@@limit}\fi
+ \edef\typog@@limit{\typog@triple@get@iii{\typog@stretchlimits}}%
+ \unless\ifx\typog@@limit\typog@@star\edef\typog@stretch@iii{\number\typog@@limit}\fi}
+
+\DeclareOptionX<typog>{breakpenalty}%
+ {\renewcommand*{\typog@breakpenalty}{#1}}
+\DeclareOptionX<typog>{debug}{\typog@debugtrue}
+\DeclareOptionX<typog>{mathitalicscorrection}[.4mu]%
+ {\typog@mathitalicscorrection=#1\relax}%
+\DeclareOptionX<typog>{nodebug}{\typog@debugfalse}
+\DeclareOptionX<typog>{textitalicscorrection}[.02em]%
+ {\setlength{\typog@textitalicscorrection}{#1}}
+\DeclareOptionX<typog>{ligaturekern}[.033333em]%
+ {\setlength{\typog@ligaturekern}{#1}}
+\DeclareOptionX<typog>{raisecapitaldash}[\z@]%
+ {\setlength{\typog@raisecapitaldash}{#1}}
+\DeclareOptionX<typog>{raisecapitalguillemets}[\z@]%
+ {\setlength{\typog@raisecapitalguillemets}{#1}}
+\DeclareOptionX<typog>{raisecapitalhyphen}[\z@]%
+ {\setlength{\typog@raisecapitalhyphen}{#1}}
+\DeclareOptionX<typog>{raisecapitaltimes}[\z@]%
+ {\setlength{\typog@raisecapitaltimes}{#1}}
+\DeclareOptionX<typog>{raiseguillemets}[\z@]%
+ {\setlength{\typog@raiseguillemets}{#1}}
+\DeclareOptionX<typog>{raisefiguredash}[\z@]%
+ {\setlength{\typog@raisefiguredash}{#1}}
+\DeclareOptionX<typog>{raise*}[\z@]%
+ {\setlength{\typog@raisecapitaldash}{#1}%
+ \setlength{\typog@raisecapitalhyphen}{#1}%
+ \setlength{\typog@raisecapitaltimes}{#1}%
+ \setlength{\typog@raisefiguredash}{#1}}
+\DeclareOptionX<typog>{shrinklimits}%
+ [\typog@default@shrink@i, \typog@default@shrink@ii, \typog@default@shrink@iii]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `shrinklimits' can only be used in the preamble}%
+ \else
+ \edef\typog@shrinklimits{#1}%
+ \typog@set@shrink@limits
+ \fi}
+\DeclareOptionX<typog>{slashkern}[.05em]%
+ {\setlength{\typog@slashkern}{#1}}
+\DeclareOptionX<typog>{stretchlimits}%
+ [\typog@default@stretch@i, \typog@default@stretch@ii, \typog@default@stretch@iii]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `stretchlimits' can only be used in the preamble}%
+ \else
+ \edef\typog@stretchlimits{#1}%
+ \typog@set@stretch@limits
+ \fi}
+\DeclareOptionX<typog>{trackingttspacing}[\typog@trackingttspacing]%
+ {\typog@require@preloaded@microtype
+ \ifx\@onlypreamble\@notprerr
+ \PackageWarning{typog}{option `trackingttspacing' can only be used in the preamble}%
+ \else
+ \typog@typeout{trackingttspacing=#1}%
+ \SetTracking[outer spacing={#1}]{encoding=*, family=tt*}{0}%
+ \fi}
+
+\newcommand*{\typog@initialize@options}
+ {\ExecuteOptionsX<typog>{
+ ligaturekern,
+ mathitalicscorrection, textitalicscorrection,
+ raisecapitaldash, raisecapitalhyphen, raisecapitaltimes,
+ raiseguillemets, raisecapitalguillemets,
+ raisefiguredash,
+ slashkern}
+ \ifdefined\MT@MT
+ \unless\ifx\@onlypreamble\@notprerr
+ \ExecuteOptionsX<typog>{shrinklimits, stretchlimits}
+ \fi
+ \fi}
+
+\typog@initialize@options
+\ProcessOptionsX<typog>
+
+\NewDocumentEnvironment{typogsetup}{m}
+ {\def\typog@@arg{#1}%
+ \ifx\typog@@arg\empty
+ \typog@initialize@options
+ \else
+ \setkeys{typog}{#1}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+\NewDocumentCommand{\typogget}{m}{\csname typog@#1\endcsname}
+
+\ExplSyntaxOn
+\newcommand*{\typog@round@dim@to@tenths}[1]
+ {\fp_to_decimal:n {round(10 * \dim_to_fp:n{#1} / 1\p@) / 10}}
+\ExplSyntaxOff
+
+\newcommand*{\typog@formatsizeinfo}[3]
+ {#1#3\kernedslash #2#3}
+
+\NewDocumentCommand{\fontsizeinfo}{s m}
+ {\global\expandafter\edef\csname typog@fontsize@#2\endcsname
+ {\typog@round@dim@to@tenths{\fontdimen6\font}}%
+ \global\expandafter\edef\csname typog@linespacing@#2\endcsname
+ {\typog@round@dim@to@tenths{\baselineskip}}%
+ \protected\expandafter\gdef\csname #2\endcsname
+ {\@ifnextchar*{\typog@formatsizeinfo
+ {\csname typog@fontsize@#2\endcsname}%
+ {\csname typog@linespacing@#2\endcsname}%
+ {}% no unit
+ \ignorespaces % eat spaces after star
+ \@gobble} % consume the star itself
+ {\typog@formatsizeinfo
+ {\csname typog@fontsize@#2\endcsname}%
+ {\csname typog@linespacing@#2\endcsname}%
+ {\,pt}% decorative unit `pt'
+ }}}
+
+\newcommand*{\typog@default@inspect@id@prefix}{a-}
+\newcounter{typog@inspect@count}
+\define@key[typog]{typoginspect}{tracingboxes}[\maxdimen]%
+ {\def\typog@@typoginspect@tracingboxes{#1}}
+\NewDocumentEnvironment{typoginspect}{O{} m}
+ {\def\typog@@typoginspect@tracingboxes{\m@ne}%
+ \setkeys[typog]{typoginspect}{#1}%
+ \edef\typog@@arg{#2}%
+ \ifx\typog@@arg\empty
+ \stepcounter{typog@inspect@count}%
+ \edef\typog@@id{\typog@default@inspect@id@prefix\arabic{typog@inspect@count}}%
+ \else
+ \edef\typog@@id{\typog@trim@spaces{\typog@@arg}}%
+ \fi
+ \typeout{<typog-inspect id="\typog@@id" job="\jobname" line="\the\inputlineno" page="\the\value{page}">}%
+ \hbadness=\m@ne
+ \vbadness=\m@ne
+ \tracingnone
+ \tracingpages=\@ne
+ \tracingparagraphs=\@ne
+ \showboxbreadth=\typog@@typoginspect@tracingboxes
+ \showboxdepth=\typog@@typoginspect@tracingboxes}
+ {\typeout{</typog-inspect>}%
+ \ignorespacesafterend}
+\NewDocumentEnvironment{typoginspectpar}{m}
+ {\typoginspect{#1}}
+ {\par\endtypoginspect}
+
+\newcommand*{\typog@allowhyphenation}
+ {\ifvmode
+ \relax
+ \else
+ \nobreak
+ \hskip\z@skip
+ \fi}
+
+\unless\ifdefined\allowhyphenation
+ \let\allowhyphenation=\typog@allowhyphenation
+\fi
+
+\NewDocumentCommand{\breakpoint}{s}
+ {\discretionary{}{}{}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@allowhyphenation}}
+
+\typog@register@pdfsubstitute{
+ \def\breakpoint#1{\if*\detokenize{#1}\ignorespaces\fi}%
+}
+
+\NewDocumentEnvironment{hyphenmin}{o m}
+ {\lefthyphenmin=\IfNoValueTF{#1}{#2}{#1}%
+ \righthyphenmin=#2}
+ {}
+
+\newcommand*{\typog@hyphen}{\char`-}
+
+\NewDocumentCommand{\nolig}{s o}
+ {\dimen0=\IfNoValueTF{#2}{\typog@ligaturekern}{#2\typog@dim@unit}%
+ \IfBooleanTF{#1}%
+ {\kern\dimen0\ignorespaces}%
+ {\discretionary{\typog@hyphen}{}{\kern\dimen0}%
+ \typog@allowhyphenation
+ \IfNoValueF{#2}{\ignorespaces}}}
+
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\nolig}{s o m}{%
+ \ifx\typog@TYPOG#3\typog@TYPOG
+ \relax
+ \else
+ \ifx\relax#3\relax
+ \relax
+ \else
+ \PackageError{typog}
+ {Missing third argument of \nolig}
+ {Append empty group or \relax after macro invocation}
+ \fi
+ \fi}
+}
+
+\newcommand*{\typog@itcorr@text@unconditional}[1]
+ {\kern#1\typog@textitalicscorrection}
+\newcommand*{\typog@itcorr@text}[1]
+ {\def\typog@@strength{#1}%
+ \dimen0=\fontdimen1\font
+ \ifdim\dimen0=\z@
+ \typog@itcorr@text@unconditional{\typog@@strength}%
+ \else
+ \kern\typog@@strength\dimen0
+ \fi}
+\newcommand*{\typog@itcorr@math}[1]
+ {\mkern#1\typog@mathitalicscorrection}
+\NewDocumentCommand{\itcorr}{s m}
+ {\ifmmode
+ \typog@itcorr@math{#2}%
+ \else
+ \IfBooleanTF{#1}%
+ {\typog@itcorr@text{#2}}%
+ {\typog@itcorr@text@unconditional{#2}}%
+ \fi}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\itcorr}{s m}{}
+}
+
+\newcommand*{\typog@forwardslash}{\char`/}
+\NewDocumentCommand{\kernedslash}{s}
+ {\hspace*{\typog@slashkern}%
+ \typog@forwardslash
+ \IfBooleanTF{#1}%
+ {\hspace*{\typog@slashkern}\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation\hspace*{\typog@slashkern}}}
+\typog@register@pdfsubstitute{
+ \def\kernedslash#1{\if*\detokenize{#1}/\ignorespaces\else/#1\fi}%
+}
+
+\NewDocumentCommand{\kernedhyphen}{s O{0} m m}
+ {\ifmmode
+ \mspace{\muexpr(#3 mu) * 18 / 1000}%
+ \raisebox{#2\typog@dim@unit}{$\m@th\mathord{-}$}%
+ \mspace{\muexpr(#4 mu) * 18 / 1000}%
+ \else
+ \def\typog@@auto{*}%
+ \def\typog@@optarg{#2}%
+ \hspace*{#3\typog@dim@unit}%
+ \raisebox{\ifx\typog@@optarg\typog@@auto
+ \typog@raisecapitalhyphen
+ \else
+ \typog@@optarg\typog@dim@unit
+ \fi}{\typog@hyphen}%
+ \hspace{#4\typog@dim@unit}%
+ \IfBooleanT{#1}{\nobreak}%
+ \fi}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\kernedhyphen}{s o m m}{-}
+}
+\NewDocumentCommand{\leftkernedhyphen}{s O{0} m}
+ {\IfBooleanTF{#1}%
+ {\kernedhyphen*[#2]{#3}{0}\ignorespaces}%
+ {\kernedhyphen[#2]{#3}{0}}}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\leftkernedhyphen}{s o m}{-}
+}
+
+\NewDocumentCommand{\rightkernedhyphen}{s O{0} m}
+ {\IfBooleanTF{#1}%
+ {\kernedhyphen*[#2]{0}{#3}\ignorespaces}%
+ {\kernedhyphen[#2]{0}{#3}}}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\rightkernedhyphen}{s o m}{-}
+}
+
+\newcommand*{\typog@breakpoint}
+ {\penalty\typog@breakpenalty}
+\NewDocumentCommand{\capitalhyphen}{s}
+ {\raisebox{\typog@raisecapitalhyphen}{\typog@hyphen}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+\typog@register@pdfsubstitute{
+ \def\capitalhyphen#1{%
+ \if*\detokenize{#1}%
+ -\ignorespaces
+ \else
+ -#1%
+ \fi}
+}
+
+\NewDocumentCommand{\capitalendash}{s}
+ {\raisebox{\typog@raisecapitaldash}{\textendash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+\let\capitaldash=\capitalendash
+\typog@register@pdfsubstitute{
+ \def\capitalendash#1{%
+ \if*\detokenize{#1}%
+ \textendash\ignorespaces
+ \else
+ \textendash#1%
+ \fi}
+ \let\capitaldash=\capitalendash
+}
+
+\NewDocumentCommand{\capitalemdash}{s}
+ {\raisebox{\typog@raisecapitaldash}{\textemdash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+\typog@register@pdfsubstitute{
+ \def\capitalemdash#1{%
+ \if*\detokenize{#1}%
+ \textemdash\ignorespaces
+ \else
+ \textemdash#1%
+ \fi}
+}
+
+\NewDocumentCommand{\figuredash}{s}
+ {\raisebox{\typog@raisefiguredash}{\textendash}%
+ \IfBooleanTF{#1}%
+ {\ignorespaces}%
+ {\typog@breakpoint\typog@allowhyphenation}}
+\typog@register@pdfsubstitute{\let\figuredash=\capitaldash}
+
+\NewDocumentCommand{\capitaltimes}{}
+ {\ifmmode
+ \mathbin{\raisebox{\typog@raisecapitaltimes}{$\m@th\times$}}%
+ \else
+ \raisebox{\typog@raisecapitaltimes}{\texttimes}%
+ \fi}
+\typog@register@pdfsubstitute{
+ \RenewExpandableDocumentCommand{\capitaltimes}{}{\texttimes}
+}
+
+\NewDocumentCommand{\singleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raiseguillemets}{\guilsinglleft}}
+\typog@register@pdfsubstitute{\let\singleguillemetleft\guilsinglleft}
+\NewDocumentCommand{\singleguillemetright}{}
+ {\raisebox{\typog@raiseguillemets}{\guilsinglright}%
+ \typog@allowhyphenation}
+\typog@register@pdfsubstitute{\let\singleguillemetright\guilsinglright}
+\NewDocumentCommand{\doubleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raiseguillemets}{\guillemotleft}}
+\typog@register@pdfsubstitute{\let\doubleguillemetleft\guillemotleft}
+\NewDocumentCommand{\doubleguillemetright}{}
+ {\raisebox{\typog@raiseguillemets}{\guillemotright}%
+ \typog@allowhyphenation}
+\typog@register@pdfsubstitute{\let\doubleguillemetright\guillemotright}
+\NewDocumentCommand{\Singleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raisecapitalguillemets}{\guilsinglleft}}
+\typog@register@pdfsubstitute{\let\Singleguillemetleft\guilsinglleft}
+\NewDocumentCommand{\Singleguillemetright}{}
+ {\raisebox{\typog@raisecapitalguillemets}{\guilsinglright}%
+ \typog@allowhyphenation}
+\typog@register@pdfsubstitute{\let\Singleguillemetright\guilsinglright}
+\NewDocumentCommand{\Doubleguillemetleft}{}
+ {\typog@allowhyphenation
+ \raisebox{\typog@raisecapitalguillemets}{\guillemotleft}}
+\typog@register@pdfsubstitute{\let\Doubleguillemetleft\guillemotleft}
+\NewDocumentCommand{\Doubleguillemetright}{}
+ {\raisebox{\typog@raisecapitalguillemets}{\guillemotright}%
+ \typog@allowhyphenation}
+\typog@register@pdfsubstitute{\let\Doubleguillemetright\guillemotright}
+
+\NewDocumentEnvironment{lastlineraggedleftpar}{}
+ {\lastlinefit=0%
+ \setlength{\leftskip}{\z@ \@plus 1fil}%
+ \setlength{\rightskip}{-\leftskip}%
+ \setlength{\parfillskip}{\leftskip}}
+ {\par}
+\let\lastlineflushrightpar=\lastlineraggedleftpar
+\let\endlastlineflushrightpar=\endlastlineraggedleftpar
+
+\NewDocumentEnvironment{lastlinecenteredpar}{}
+ {\lastlinefit=0%
+ \setlength{\leftskip}{\z@ \@plus .5fil}%
+ \setlength{\rightskip}{-\leftskip}%
+ \setlength{\parfillskip}{\z@ \@plus 1fil}}
+ {\par}
+
+\NewDocumentEnvironment{shortenpar}{}
+ {\advance\looseness by -1
+ \ifnum\tracingparagraphs>0
+ \typeout{@ looseness \the\looseness}%
+ \fi}
+ {\par}
+
+\NewDocumentEnvironment{prolongpar}{}
+ {\finalhyphendemerits=100000001
+ \advance\looseness by 1
+ \ifnum\tracingparagraphs>0
+ \typeout{@ looseness \the\looseness}%
+ \fi}
+ {\par}
+
+\newcommand*{\typog@covernextindentpar@zero@parindent}{2em}
+\newcommand*{\typog@covernextindentpar@nonzero@parindent}{2\parindent}
+\NewDocumentEnvironment{covernextindentpar}{o}
+ {\IfNoValueTF{#1}
+ {\ifdim\parindent=\z@
+ \dimen0=\dimexpr\linewidth - \typog@covernextindentpar@zero@parindent
+ \else
+ \dimen0=\dimexpr\linewidth - \typog@covernextindentpar@nonzero@parindent
+ \fi}
+ {\dimen0=\dimexpr\linewidth - (#1)}%
+ \parfillskip=\dimen0 \@minus \dimen0
+ \relax}
+ {\par}
+
+\newcommand*{\typog@openlastlinepar@zero@parindent}{2em}
+\newcommand*{\typog@openlastlinepar@nonzero@parindent}{2\parindent}
+\NewDocumentEnvironment{openlastlinepar}{o}
+ {\IfNoValueTF{#1}
+ {\ifdim\parindent=\z@
+ \skip0=\typog@openlastlinepar@zero@parindent
+ \@plus 1fil
+ \@minus \typog@openlastlinepar@zero@parindent
+ \else
+ \skip0=\typog@openlastlinepar@nonzero@parindent
+ \@plus 1fil
+ \@minus \typog@openlastlinepar@nonzero@parindent
+ \fi}
+ {\dimen0=\dimexpr#1\relax
+ \skip0=\dimen0 \@plus 1fil \@minus \dimen0}
+ \parfillskip=\skip0}
+ {\par}
+
+\newcommand*{\widespacestrength}{1.}
+\newcommand*{\widespacescale}{1.125}
+\NewDocumentCommand{\widespace}{s}
+ {\IfBooleanTF{#1}%
+ {\dimen0=\widespacescale\fontdimen2\font}%
+ {\ifdim\fontdimen7\font=\z@
+ \dimen0=\widespacescale\fontdimen2\font
+ \else
+ \dimen0=\dimexpr\fontdimen2\font +
+ \widespacestrength\fontdimen7\font
+ \fi}%
+ \hskip \glueexpr\dimen0
+ \@plus \widespacescale\fontdimen3\font
+ \@minus \widespacescale\fontdimen4\font
+ \ignorespaces}
+
+\newcommand*{\narrowspacestrength}{.5}
+\newcommand*{\narrowspacescale}{.9375}
+\NewDocumentCommand{\narrowspace}{s}
+ {\IfBooleanTF{#1}%
+ {\dimen0=\narrowspacescale\fontdimen2\font}%
+ {\ifdim\fontdimen7\font=\z@
+ \dimen0=\narrowspacescale\fontdimen2\font
+ \else
+ \dimen0=\dimexpr\fontdimen2\font -
+ \narrowspacestrength\fontdimen7\font
+ \fi}%
+ \hskip \glueexpr\dimen0
+ \@plus \narrowspacescale\fontdimen3\font
+ \@minus \narrowspacescale\fontdimen4\font
+ \ignorespaces}
+
+\NewDocumentEnvironment{loosespacing}{O{1}}
+ {\dimen2=\fontdimen2\font
+ \ifcase #1
+ \spaceskip=\z@
+ \or % 1 +5%
+ \spaceskip=1.05\dimen2 \@plus .5\dimen2 \@minus .1\dimen2
+ \or % 2 +10%
+ \spaceskip=1.1\dimen2 \@plus .5\dimen2 \@minus .1\dimen2
+ \or % 3 +20%
+ \spaceskip=1.2\dimen2 \@plus .6\dimen2 \@minus .2\dimen2
+ \else % >= 4 +30%
+ \spaceskip=1.3\dimen2 \@plus .8\dimen2 \@minus .3\dimen2
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{tightspacing}{O{1}}
+ {\dimen2=\fontdimen2\font
+ \ifcase #1
+ \spaceskip=\z@
+ \or % 1 -1.25%
+ \spaceskip=.9875\dimen2 \@plus .0125\dimen2 \@minus .5\dimen2
+ \or % 2 -2.5%
+ \spaceskip=.975\dimen2 \@plus .025\dimen2 \@minus .5\dimen2
+ \or % 3 -5%
+ \spaceskip=.95\dimen2 \@plus .05\dimen2 \@minus .5\dimen2
+ \else % >= 4 -10%
+ \spaceskip=.9\dimen2 \@plus .1\dimen2 \@minus .5\dimen2
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{setfonttracking}{m}
+ {\edef\MT@letterspace@{#1}%
+ \lsstyle
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\newcommand*{\typog@setup@font@expansion}
+ {\SetExpansion
+ [context = typog@shrink1,
+ shrink = \typog@shrink@i,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@shrink2,
+ shrink = \typog@shrink@ii,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@shrink3,
+ shrink = \typog@shrink@iii,
+ stretch = 0]%
+ {encoding = {*}}%
+ {}
+
+ \SetExpansion
+ [context = typog@stretch1,
+ shrink = 0,
+ stretch = \typog@stretch@i]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@stretch2,
+ shrink = 0,
+ stretch = \typog@stretch@ii]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@stretch3,
+ shrink = 0,
+ stretch = \typog@stretch@iii]%
+ {encoding = {*}}%
+ {}
+
+ \SetExpansion
+ [context = typog@expand1,
+ shrink = \typog@shrink@i,
+ stretch = \typog@stretch@i]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@expand2,
+ shrink = \typog@shrink@ii,
+ stretch = \typog@stretch@ii]%
+ {encoding = {*}}%
+ {}
+ \SetExpansion
+ [context = typog@expand3,
+ shrink = \typog@shrink@iii,
+ stretch = \typog@stretch@iii]%
+ {encoding = {*}}%
+ {}}
+\newcommand*{\typog@test@microtype@expansion@feature}
+ {\ifMT@expansion
+ \typog@typeout{microtype preloaded -- font expansion features available}%
+ \def\typog@require@microtype@expansion{\relax}
+ \typog@setup@font@expansion
+ \else
+ \PackageWarning{typog}{microtype preloaded,\space
+ but font expansion is disabled}%
+ \def\typog@require@microtype@expansion
+ {\PackageError{typog}
+ {microtype font expansion disabled}
+ {pass option `expansion' to package microtype}}
+ \fi}
+\iftypog@microtype@preloaded
+ \typog@test@microtype@expansion@feature
+\else
+ \def\typog@require@microtype@expansion
+ {\PackageError{typog}%
+ {package microtype not (pre-)loaded, %
+ which is required for typog's font expansion}%
+ {require package microtype before package typog}}
+\fi
+
+\NewDocumentEnvironment{setfontshrink}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@shrink1}%
+ \or % 2
+ \microtypecontext{expansion=typog@shrink2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@shrink3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{setfontstretch}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@stretch1}%
+ \or % 2
+ \microtypecontext{expansion=typog@stretch2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@stretch3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{setfontexpand}{O{1}}
+ {\typog@require@microtype@expansion
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \microtypecontext{expansion=typog@expand1}%
+ \or % 2
+ \microtypecontext{expansion=typog@expand2}%
+ \else % >= 3
+ \microtypecontext{expansion=typog@expand3}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{nofontexpansion}{}
+ {\ifdefined\microtypesetup
+ \microtypesetup{expansion=false}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+\let\nofontexpand=\nofontexpansion
+\let\endnofontexpand=\endnofontexpansion
+
+\NewDocumentEnvironment{nocharprotrusion}{}
+ {\ifdefined\microtypesetup
+ \microtypesetup{protrusion=false}%
+ \fi
+ \ignorespaces}
+ {\ignorespacesafterend}
+
+\newcommand*{\typog@scaled@emergencystretch}[1]
+ {\emergencystretch=\ifdim\linewidth=\z@
+ #1%
+ \else
+ \dimexpr (#1) * \linewidth / \textwidth
+ \fi}
+
+\NewDocumentCommand{\slightlysloppy}{O{1}}
+ {\ifcase #1% 0
+ % \tolerance=200
+ % \emergencystretch=\z@
+ % \hfuzz=.1\p@
+ % \vfuzz=\hfuzz
+ \fussy
+ \or % 1
+ \pretolerance=165%
+ \tolerance=330%
+ \typog@scaled@emergencystretch{.375em}%
+ \hfuzz=.15\p@
+ \vfuzz=\hfuzz
+ \or % 2
+ \pretolerance=265%
+ \tolerance=530%
+ \typog@scaled@emergencystretch{.75em}%
+ \hfuzz=.15\p@
+ \vfuzz=\hfuzz
+ \or % 3
+ \pretolerance=435%
+ \tolerance=870%
+ \typog@scaled@emergencystretch{1.125em}%
+ \hfuzz=.2\p@
+ \vfuzz=\hfuzz
+ \or % 4
+ \pretolerance=705%
+ \tolerance=1410%
+ \typog@scaled@emergencystretch{1.5em}%
+ \hfuzz=.3\p@
+ \vfuzz=\hfuzz
+ \or % 5
+ \pretolerance=1155%
+ \tolerance=2310%
+ \typog@scaled@emergencystretch{1.875em}%
+ \hfuzz=.35\p@
+ \vfuzz=\hfuzz
+ \or % 6
+ \pretolerance=1880%
+ \tolerance=3760%
+ \typog@scaled@emergencystretch{2.25em}%
+ \hfuzz=.4\p@
+ \vfuzz=\hfuzz
+ \or % 7
+ \pretolerance=3065%
+ \tolerance=6130%
+ \typog@scaled@emergencystretch{2.625em}%
+ \hfuzz=.45\p@
+ \vfuzz=\hfuzz
+ \else % >= 8
+ % \tolerance=9999
+ % \emergencystretch=3em
+ % \hfuzz=.5\p@
+ % \vfuzz=\hfuzz
+ \sloppy
+ \fi
+ \ignorespaces}
+\NewDocumentEnvironment{slightlysloppypar}{O{1}}
+ {\par\slightlysloppy[#1]\ignorespaces}
+ {\par}
+
+\ExplSyntaxOn
+\newcommand*{\typog@geometric@mean}[2]
+ {\fp_to_int:n {sqrt((#1) * (#2))}}
+\ExplSyntaxOff
+
+\newcounter{typog@mean@penalty}
+
+\NewDocumentCommand{\vtietop}{O{3}}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\clubpenalty}}%
+ \typog@typeout{vtietop: penalties \the\@M--\the\value{typog@mean@penalty}--\the\clubpenalty}%
+ \unless\ifnum\clubpenalty<\@M
+ \PackageWarning{typog}{vtietop: clubpenalty=\the\clubpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \clubpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 3
+ \clubpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 4
+ \clubpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 5
+ \clubpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 6
+ \clubpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 7
+ \clubpenalties 8
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \or % 8
+ \clubpenalties 9
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \else % >= 9
+ \clubpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \clubpenalty
+ \fi}
+
+\NewDocumentEnvironment{vtietoppar}{O{3}}
+ {\vtietop[#1]}
+ {\par
+ \ignorespacesafterend}
+
+\NewDocumentCommand{\splicevtietop}{O{3}}
+ {\let\typog@old@item=\@item
+ \def\@item[##1]{\typog@old@item[##1]\vtietop[#1]}%
+ \ignorespaces}
+
+\ifdefined\SetEnumitemKey
+ \SetEnumitemKey{vtietop}{first=\splicevtietop}
+\fi
+
+\NewDocumentCommand{\vtiebot}{O{3}}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\widowpenalty}}%
+ \typog@typeout{vtiebot: penalties \the\@M--\the\value{typog@mean@penalty}--\the\widowpenalty}%
+ \unless\ifnum\widowpenalty<\@M
+ \PackageWarning{typog}{vtiebot: widowpenalty=\the\widowpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \widowpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 3
+ \widowpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 4
+ \widowpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 5
+ \widowpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 6
+ \widowpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 7
+ \widowpenalties 8
+ \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \or % 8
+ \widowpenalties 9
+ \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \else % >= 9
+ \widowpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \widowpenalty
+ \fi}
+
+\NewDocumentEnvironment{vtiebotpar}{O{3}}
+ {\vtiebot[#1]}
+ {\par
+ \ignorespacesafterend}
+
+\NewDocumentCommand{\typog@vtiebotdisp}{m}
+ {\setcounter{typog@mean@penalty}
+ {\typog@geometric@mean{\@M}{\displaywidowpenalty}}%
+ \typog@typeout{vtiebotdisp: penalties \the\@M--\the\value{typog@mean@penalty}--\the\displaywidowpenalty}%
+ \unless\ifnum\displaywidowpenalty<\@M
+ \PackageWarning{typog}{vtiebotdisp: displaywidowpenalty=\the\displaywidowpenalty\space>= 10000}%
+ \fi
+ \ifcase#1% 0
+ \relax
+ \or % 1
+ \relax
+ \or % 2
+ \displaywidowpenalties 3
+ \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 3
+ \displaywidowpenalties 4
+ \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 4
+ \displaywidowpenalties 5
+ \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 5
+ \displaywidowpenalties 6
+ \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 6
+ \displaywidowpenalties 7
+ \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 7
+ \displaywidowpenalties 8
+ \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \or % 8
+ \displaywidowpenalties 9
+ \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \else % >= 9
+ \displaywidowpenalties 10
+ \@M \@M \@M \@M \@M \@M \@M \@M
+ \value{typog@mean@penalty}
+ \displaywidowpenalty
+ \fi}
+
+\NewDocumentEnvironment{vtiebotdisp}{O{3}}
+ {\typog@vtiebotdisp{#1}}
+ {\ignorespacesafterend}
+
+\NewDocumentEnvironment{vtiebotdisptoppar}{O{3}o}
+ {\postdisplaypenalty=\@M
+ \predisplaypenalty=10001% in accordance with package `widows-and-orphans'
+ \edef\typog@@top@lines{\IfNoValueTF{#2}{#1}{#2}}%
+ \edef\typog@@after@display@math{\vtietop[\typog@@top@lines]}%
+ \PushPostHook{display}{\aftergroup\typog@@after@display@math}%
+ \vtiebotdisp[#1]}
+ {\par
+ \PopPostHook{display}%
+ \ignorespacesafterend}
+
+\newenvironment*{breakabledisplay}[1][3]
+ {\allowdisplaybreaks[#1]}
+ {\ignorespacesafterend}
+
+\newcommand*{\typog@setbaselineskip@iter@limit}{10}
+\newcommand*{\typog@setbaselineskip@relative@error}{.001}
+\ExplSyntaxOn
+\cs_new:Npn \typog@setbaselineskip #1
+{
+ \int_set:Nn \l_tmpa_int {1}
+ \int_set:Nn \l_tmpb_int {\typog@setbaselineskip@iter@limit}
+ \dim_set:Nn \l_tmpa_dim {\glueexpr #1}
+
+ \typog@typeout{\string\setbaselineskip:\space
+ initial\space baselineskip:\space \the\baselineskip}
+ \typog@typeout{\string\setbaselineskip:\space
+ target\space baselineskip:\space \dim_use:N \l_tmpa_dim}
+
+ \dim_compare:nNnTF {\baselineskip} > {\c_zero_dim}
+ {}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space
+ baselineskip\space not\space positive}
+ {}
+ }
+
+ \dim_compare:nNnTF {\l_tmpa_dim} > {\c_zero_dim}
+ {}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space target\space
+ baselineskip\space must\space be\space
+ positive}
+ {}
+ }
+
+ \skip_if_eq:nnTF {\l_tmpa_dim} {\glueexpr #1}
+ {}
+ {
+ \PackageWarning{typog}
+ {\string\setbaselineskip:\space argument\space
+ is\space a\space skip;\space
+ will\space ignore\space glue}
+ {}
+ }
+
+ \fp_set:Nn \l_tmpa_fp {\l_tmpa_dim / \baselineskip}
+ \fp_until_do:nNnn {abs(\l_tmpa_dim / \baselineskip - 1)} <
+ {\typog@setbaselineskip@relative@error}
+ {
+ \setstretch{\fp_use:N \l_tmpa_fp}
+ \fp_set:Nn \l_tmpa_fp
+ {\l_tmpa_fp * \l_tmpa_dim / \baselineskip}
+
+ \int_incr:N \l_tmpa_int
+ \int_compare:nNnTF {\l_tmpa_int} > {\l_tmpb_int}
+ {
+ \PackageError{typog}
+ {\string\setbaselineskip:\space excessive\space
+ number\space of\space iterations:\space
+ \int_use:N \l_tmpa_int\space >\space
+ \int_use:N \l_tmpb_int}
+ {}
+ }
+ {}
+ }
+
+ \typog@typeout{\string\setbaselineskip:\space
+ final\space \string\setstretch\space argument:\space
+ \fp_use:N \l_tmpa_fp}
+ \typog@typeout{\string\setbaselineskip:\space
+ final\space baselineskip:\space \the\baselineskip}
+}
+
+\cs_new:Npn \setbaselineskip #1
+{
+ \AfterPreamble{\typog@setbaselineskip{#1}}
+ \ignorespaces
+}
+
+\cs_new:Npn \resetbaselineskip
+{
+ \AfterPreamble{\setstretch{1}}
+}
+
+\dim_new:N \typogfontsize
+\AfterEndPreamble{
+ \dim_set:Nn \typogfontsize {\fontdimen6\font}
+ \typog@typeout{\string\typogfontsize =
+ \dim_use:N \typogfontsize\space
+ (at\space begin\space of\space document)}
+}
+
+\cs_new:Npn \setbaselineskippercentage #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{
+ \fp_eval:n {(#1) / 100} \typogfontsize}
+ }
+ {
+ \PackageError{typog}
+ {\string\setbaselineskippercentage:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+
+\cs_new:Npn \setleading #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{\typogfontsize + \dimexpr #1}
+ }
+ {
+ \PackageError{typog}
+ {\string\setleading:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+
+\cs_new:Npn \setleadingpercentage #1
+{
+ \AfterPreamble{
+ \dim_compare:nNnTF {\typogfontsize} > {\c_zero_dim}
+ {
+ \typog@setbaselineskip{
+ \fp_eval:n {1 + (#1) / 100} \typogfontsize}
+ }
+ {
+ \PackageError{typog}
+ {\string\setleadingpercentage:\space
+ \string\typogfontsize <= 0}
+ {Maybe\space \string\typogfontsize\space
+ is\space uninitialized?}
+ }
+ }
+ \ignorespaces
+}
+\ExplSyntaxOff
+
+\ExplSyntaxOn
+\cs_new_eq:NN \typog@repeat \prg_replicate:nn
+
+\newcommand*{\typog@mod}[2]{\int_mod:nn{#1}{#2}}
+\ExplSyntaxOff
+
+\newcommand*{\typog@triplet@max@lines}{99}
+
+\define@key[typog]{smoothraggedrightshapetriplet}{leftskip}%
+ {\def\typog@@triplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapetriplet}{parindent}%
+ {\def\typog@@triplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapetriplet}{O{} m m m}
+ {\def\typog@@triplet@leftskip{\z@}%
+ \def\typog@@triplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapetriplet}{#1}%
+ \skip0=\typog@@triplet@leftskip\relax
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \typog@typeout{smoothraggedrightshapetriplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapetriplet: skip3=\the\skip3}%
+ \unless\ifnum\typog@mod{\typog@triplet@max@lines}{3}=0
+ \PackageError{typog}
+ {Line number of triplet generator %
+ (\typog@triplet@max@lines) not divisible by 3}
+ {}
+ \fi
+ \edef\typog@@triplet@linespecs{%
+ \glueexpr \skip0 + \typog@@triplet@parindent\relax
+ \glueexpr \skip1 - \typog@@triplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3
+ \typog@repeat{\numexpr\typog@triplet@max@lines / 3 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3}}
+ \parshape=\typog@triplet@max@lines\typog@@triplet@linespecs\relax}
+ {\par}
+
+\newcommand*{\typog@quintuplet@max@lines}{95}
+
+\define@key[typog]{smoothraggedrightshapequintuplet}{leftskip}
+ {\def\typog@@quintuplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapequintuplet}{parindent}
+ {\def\typog@@quintuplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapequintuplet}{O{} m m m m m}
+ {\def\typog@@quintuplet@leftskip{\z@}%
+ \def\typog@@quintuplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapequintuplet}{#1}%
+ \skip0=\typog@@quintuplet@leftskip
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \skip4=#5\relax
+ \skip5=#6\relax
+ \typog@typeout{smoothraggedrightshapequintuplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip3=\the\skip3}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip4=\the\skip4}%
+ \typog@typeout{smoothraggedrightshapequintuplet: skip5=\the\skip5}%
+ \unless\ifnum\typog@mod{\typog@quintuplet@max@lines}{5}=0
+ \PackageError{typog}
+ {Line number of quintuplet generator %
+ (\typog@quintuplet@max@lines) not divisible by 5}
+ {}
+ \fi
+ \edef\typog@@quintuplet@linespecs{%
+ \glueexpr \skip0 + \typog@@quintuplet@parindent\relax
+ \glueexpr \skip1 - \typog@@quintuplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5
+ \typog@repeat{\numexpr\typog@quintuplet@max@lines / 5 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5}}
+ \parshape=\typog@quintuplet@max@lines\typog@@quintuplet@linespecs\relax}
+ {\par}
+
+\newcommand*{\typog@septuplet@max@lines}{98}
+
+\define@key[typog]{smoothraggedrightshapeseptuplet}{leftskip}%
+ {\def\typog@@septuplet@leftskip{#1}}
+\define@key[typog]{smoothraggedrightshapeseptuplet}{parindent}%
+ {\def\typog@@septuplet@parindent{#1}}
+\NewDocumentEnvironment{smoothraggedrightshapeseptuplet}{O{} m m m m m m m}
+ {\def\typog@@septuplet@leftskip{\z@}%
+ \def\typog@@septuplet@parindent{\z@}%
+ \setkeys*[typog]{smoothraggedrightshapeseptuplet}{#1}%
+ \skip0=\typog@@septuplet@leftskip
+ \skip1=#2\relax
+ \skip2=#3\relax
+ \skip3=#4\relax
+ \skip4=#5\relax
+ \skip5=#6\relax
+ \skip6=#7\relax
+ \skip7=#8\relax
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip0=\the\skip0}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip1=\the\skip1}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip2=\the\skip2}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip3=\the\skip3}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip4=\the\skip4}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip5=\the\skip5}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip6=\the\skip6}%
+ \typog@typeout{smoothraggedrightshapeseptuplet: skip7=\the\skip7}%
+ \unless\ifnum\typog@mod{\typog@septuplet@max@lines}{7}=0
+ \PackageError{typog}
+ {Line number of septuplet generator %
+ (\typog@septuplet@max@lines) not divisible by 7}
+ {}
+ \fi
+ \edef\typog@@septuplet@linespecs{%
+ \glueexpr \skip0 + \typog@@septuplet@parindent\relax
+ \glueexpr \skip1 - typog@@septuplet@parindent\relax
+ \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5 \skip0 \skip6 \skip0 \skip7
+ \typog@repeat{\numexpr\typog@septuplet@max@lines / 7 - 1}
+ {\skip0 \skip1 \skip0 \skip2 \skip0 \skip3 \skip0 \skip4 \skip0 \skip5 \skip0 \skip6 \skip0 \skip7}}
+ \parshape=\typog@septuplet@max@lines\typog@@septuplet@linespecs\relax}
+ {\par}
+
+\newcommand*{\smoothraggedrightfuzzfactor}{1.0}
+\newcommand*{\smoothraggedrightgenerator}{triplet}
+\newlength{\smoothraggedrightleftskip}
+\newlength{\smoothraggedrightparindent}
+\newlength{\smoothraggedrightragwidth}
+\setlength{\smoothraggedrightragwidth}{2em}
+
+\newdimen{\typog@fuzzwidth}
+
+\define@key[typog]{smoothraggedrightpar}{linewidth}%
+ {\def\typog@@linewidth{#1}}
+
+\NewDocumentEnvironment{smoothraggedrightpar}{O{}}
+ {\edef\typog@@linewidth{\linewidth}%
+ \setkeys[typog]{smoothraggedrightpar}{#1}%
+ \edef\typog@@generatorchoice{%
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{triplet}=\z@
+ 0%
+ \else
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{quintuplet}=\z@
+ 1%
+ \else
+ \ifnum\pdf@strcmp{\smoothraggedrightgenerator}{septuplet}=\z@
+ 2%
+ \else
+ \PackageError{typog}
+ {smoothraggedright: unknown generator name}
+ {valid generator names are triplet, quintuplet, and septuplet}%
+ \fi
+ \fi
+ \fi}%
+ \let\typog@@smoothraggedrightleftskip=\smoothraggedrightleftskip
+ \ifnum\@listdepth>0
+ \addtolength{\typog@@smoothraggedrightleftskip}{\leftmargin}%
+ \fi
+ \typog@fuzzwidth=\smoothraggedrightfuzzfactor\smoothraggedrightragwidth
+ \ifcase\typog@@generatorchoice
+ \typog@fuzzwidth=.25\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=triplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapetriplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth}% (3)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ \or
+ \typog@fuzzwidth=.125\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=quintuplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapequintuplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr (\typog@@linewidth * 4 - \smoothraggedrightragwidth * 3) / 4
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth\relax}% (5)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (3)
+ {\glueexpr (\typog@@linewidth * 4 - \smoothraggedrightragwidth) / 4
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (4)
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ \or
+ \typog@fuzzwidth=.08333\smoothraggedrightragwidth
+ \typog@typeout{smoothraggedright: generator=septuplet, typog@fuzzwidth=\the\typog@fuzzwidth}%
+ \smoothraggedrightshapeseptuplet[leftskip=\typog@@smoothraggedrightleftskip,
+ parindent=\glueexpr\smoothraggedrightparindent + \parindent,
+ #1]%
+ {\glueexpr (\typog@@linewidth * 3 - \smoothraggedrightragwidth * 2) / 3
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (3)
+ {\glueexpr (\typog@@linewidth * 6 - \smoothraggedrightragwidth) / 6
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (6)
+ {\glueexpr \typog@@linewidth - \smoothraggedrightragwidth +
+ + \glueexpr \z@ \@plus \typog@fuzzwidth\relax}% (1)
+ {\glueexpr (\typog@@linewidth * 3 - \smoothraggedrightragwidth) / 3
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (5)
+ {\glueexpr (\typog@@linewidth * 6 - \smoothraggedrightragwidth * 5) / 6
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (2)
+ {\glueexpr \typog@@linewidth \@minus \typog@fuzzwidth\relax}% (7)
+ {\glueexpr (\typog@@linewidth * 2 - \smoothraggedrightragwidth) / 2
+ + \glueexpr \z@ \@plus \typog@fuzzwidth \@minus \typog@fuzzwidth\relax}% (4)
+ \fi}
+ {\ifcase\typog@@generatorchoice
+ \endsmoothraggedrightshapetriplet
+ \or
+ \endsmoothraggedrightshapequintuplet
+ \or
+ \endsmoothraggedrightshapeseptuplet
+ \fi}
+
+\NewDocumentEnvironment{smoothraggedright}{O{}}
+ {\PushPostHook{par}{\hskip-\parindent\smoothraggedrightpar[#1]\relax}}
+ {\par\PopPostHook{par}}
+
+\endinput
+%%
+%% End of file `typog.sty'.
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index 6e0e05f252f..8a0498ea86b 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -876,7 +876,7 @@ my @TLP_working = qw(
twemoji-colr twemojis twoinone twoup twoxtwogame
txfonts txfontsb txgreeks txuprcal
type1cm typed-checklist typeface typehtml typeoutfileinfo typewriter
- typicons typoaid typogrid typstfun tzplot
+ typicons typoaid typog typogrid typstfun tzplot
uaclasses uafthesis uantwerpendocs uassign ucalgmthesis
ucharcat ucharclasses ucbthesis ucdavisthesis ucph-revy
ucs ucsmonograph
diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds
index 1b3c6a55dc8..5ffd4403824 100755
--- a/Master/tlpkg/libexec/ctan2tds
+++ b/Master/tlpkg/libexec/ctan2tds
@@ -1484,6 +1484,7 @@ chomp (my $ctan_root = `tlpkginfo --ctan-root`);
'typedref', "die 'skipping, nonfree license'",
'typespec', "die 'skipping, nonfree font specimens'",
'typingtex', "die 'skipping, ancient mac docs'",
+ 'typog', "&MAKEflatten",
'uafthesis', "&MAKEnosymlinks",
'uebungsblatt',"&MAKEflatten",
'ufrgscca', "&MAKEflatten",
@@ -3449,6 +3450,7 @@ $standardinsrunner = "latex -8bit";
'synthslant' => 'NULL', # doc
'tipfr' => 'NULL', # doc
'ticollege' => 'NULL', # doc
+ 'typog' => 'NULL', # doc
'tzplot' => 'NULL', # doc
'turnthepage' => 'NULL', # doc
'voss-mathmode' => 'NULL', # doc
@@ -3485,6 +3487,7 @@ $standardmp = '\.mp$';
'semioneside', 'NULL', # not figure*.mp
'synthslant', 'NULL', # doc figures
'textpath', 'textpath.mp', # not textpathfigs.mp
+ 'typog', 'NULL', # doc figures
);
@@ -3867,6 +3870,7 @@ $standardttf = '\.ttf|\.TTC';
'thumbpdf' => '\.pl$',
'tikztosvg' => '^tikztosvg$',
'tlcockpit' => '\.sh$',
+ 'typog' => 'typog-grep.pl$',
'ulqda' => '\.pl$',
'urlbst' => 'urlbst$',
'vpe' => '\.pl$',
@@ -3957,6 +3961,7 @@ $standardttf = '\.ttf|\.TTC';
'texlogsieve' => '\.1$',
'tikztosvg' => '\.1$',
'tlcockpit' => '\.man$',
+ 'typog' => '\.1$',
'webquiz' => '\.1$',
'wheretotrim' => '\.1$',
);
diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
index 570b25af4e3..36fc9338898 100644
--- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
@@ -1434,6 +1434,7 @@ depend type1cm
depend typed-checklist
depend typeface
depend typoaid
+depend typog
depend typogrid
depend uassign
depend ucs
diff --git a/Master/tlpkg/tlpsrc/typog.tlpsrc b/Master/tlpkg/tlpsrc/typog.tlpsrc
new file mode 100644
index 00000000000..27aa6ccdd1b
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/typog.tlpsrc
@@ -0,0 +1,3 @@
+binpattern f bin/${ARCH}/${PKGNAME}-grep
+docpattern +f texmf-dist/doc/man/man1/${PKGNAME}-grep.*
+