diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx | 1267 |
1 files changed, 1075 insertions, 192 deletions
diff --git a/Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx b/Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx index 76fb00e32b6..fdaa2e6d29a 100644 --- a/Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx +++ b/Master/texmf-dist/source/latex/unicode-math/unicode-math.dtx @@ -7,7 +7,8 @@ \input docstrip.tex \keepsilent \preamble -Copyright 2006-2010 by Will Robertson <will.robertson@latex-project.org> +Copyright 2006-2011 Will Robertson <will.robertson@latex-project.org> +Copyright 2010-2011 Philipp Stephani <st_philipp@yahoo.de> This package is free software and may be redistributed and/or modified under the conditions of the LaTeX Project Public License, version 1.3c or higher @@ -31,10 +32,10 @@ This work is "author-maintained" by Will Robertson. %</internal> %<preamble>\ProvidesPackage{unicode-math} %<*preamble> - [2010/09/27 v0.5b Unicode maths in XeLaTeX and LuaLaTeX] + [2011/01/29 v0.5d Unicode maths in XeLaTeX and LuaLaTeX] %</preamble> %<*internal> -\documentclass{ltxdoc} +\documentclass[a4paper]{ltxdoc} \usepackage{dtx-style} \begin{document} \DocInput{\jobname.dtx} @@ -47,7 +48,8 @@ This work is "author-maintained" by Will Robertson. % ^^A %%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \title{Experimental Unicode mathematical typesetting: The \pkg{unicode-math} package} -% \author{Will Robertson\\\texttt{will.robertson@latex-project.org}} +% \author{Will Robertson and Philipp Stephani\\ +% \texttt{will.robertson@latex-project.org}} % \date{\umfiledate \qquad \umfileversion} % % \maketitle @@ -72,8 +74,10 @@ This work is "author-maintained" by Will Robertson. % Maths input can also be simplified with Unicode since literal glyphs may be % entered instead of control sequences in your document source. % -% The package is fulled tested under \XeTeX, but Lua\TeX\ support is not -% yet complete. User beware, but let me know of any troubles. +% The package provides support for both \XeTeX\ and Lua\TeX. The different +% engines provide differing levels of support for Unicode maths, and +% support for Lua\TeX's features in this area is still incomplete. +% Please let us know of any troubles. % % Alongside this documentation file, you should be able to find a minimal % example demonstrating the use of the package, @@ -99,13 +103,12 @@ This work is "author-maintained" by Will Robertson. % % This document describes the \pkg{unicode-math} package, which is an % \emph{experimental} implementation of a macro to Unicode glyph encoding for -% mathematical characters. Its intended use is for \XeTeX, although it is -% conjectured that some effect could be spent to create a cross-format -% package that would also work with Lua\TeX. +% mathematical characters. % % Users who desire to specify maths alphabets only (Greek and Latin letters, % and Arabic numerals) % may wish to use Andrew Moschou's \pkg{mathspec} package instead. +% (\XeTeX-only at time of writing.) % % \section{Acknowledgements} % @@ -546,7 +549,6 @@ This work is "author-maintained" by Will Robertson. % % \subsection{Miscellanea} % -% % \subsubsection{Nabla} % \seclabel{nabla} % @@ -650,11 +652,13 @@ This work is "author-maintained" by Will Robertson. % \subsubsection{Primes} % % Primes ($x'$) may be input in several ways. You may use any combination -% of \ascii\ straight quote (\texttt{\char`\'}), Unicode prime \unichar{2032} -% ($'$), and \cs{prime}; when multiple primes occur next to each other, they chain +% the \ascii\ straight quote (\texttt{\char`\'}) or the Unicode prime \unichar{2032} +% ($'$); when multiple primes occur next to each other, they chain % together to form double, triple, or quadruple primes if the font contains -% pre-drawn glyphs. These may also be accessed with \cs{dprime}, -% \cs{trprime}, and \cs{qprime}, respectively. +% pre-drawn glyphs. The individual prime glyphs are accessed, as usual, +% with the \cs{prime} command, and the double-, triple-, and quadruple-prime +% glyphs are available with \cs{dprime}, \cs{trprime}, and \cs{qprime}, +% respectively. % % If the font does not contain the pre-drawn glyphs or more than four primes % are used, the single prime glyph is used multiple times with a negative @@ -667,12 +671,18 @@ This work is "author-maintained" by Will Robertson. % \ExplySyntaxOff % \end{verbatim} % -% Backwards or reverse primes behave in exactly the same way; use any of \ascii\ -% back tick (\texttt{\char`\`}), Unicode reverse prime \unichar{2035} -% ({\umfont\char"2035}), or \cs{backprime} to access it. -% Multiple backwards primes can also be called with \cs{backdprime}, +% Backwards or reverse primes behave in exactly the same way; use the \ascii\ +% back tick (\texttt{\char`\`}) or the Unicode reverse prime \unichar{2035} +% ({\umfont\char"2035}). +% The command to access the backprime is \cs{backprime}, and +% multiple backwards primes can accessed with \cs{backdprime}, % \cs{backtrprime}, and \cs{backqprime}. % +% In all cases above, no error checking is performed if you attempt to +% access a multi-prime glyph in a font that doesn't contain one. For this +% reason, it may be safer to write \verb|x''''| instead of \verb|x\qprime| +% in general. +% % If you ever need to enter the straight quote |'| or the backtick |`| in % maths mode, these glyphs can be accessed with \cs{mathstraightquote} and % \cs{mathbacktick}. @@ -878,6 +888,20 @@ This work is "author-maintained" by Will Robertson. % (This should be a font option rather than a package option, but % it will change soon.) % +% +% \subsubsection{Growing and non-growing accents} +% \seclabel{growing-accents} +% +% There are a few accents for which \TeX\ has both non-growing and growing +% versions. Among these are \cs{hat} and \cs{tilde}; the corresponding growing +% versions are called \cs{widehat} and \cs{widetilde}, respectively. +% +% \XeTeX\ and older versions of \LuaTeX\ do not support this distinction, however, +% and \emph{all} accents there will grow automatically. (I.e., \cs{hat} and \cs{widehat} +% are equivalent.) Unfortunately this is not always appropriate. As of \LuaTeX\ v0.65, +% these wide/non-wide commands will again behave in their expected manner. +% +% % \subsubsection{Pre-drawn fraction characters} % % Pre-drawn fractions \unichar{00BC}--\unichar{00BE}, \unichar{2150}--\unichar{215E} @@ -1022,19 +1046,16 @@ This work is "author-maintained" by Will Robertson. \RequirePackage{expl3}[2009/08/12] \RequirePackage{xparse}[2009/08/31] \RequirePackage{l3keys2e} -\RequirePackage{fontspec}[2010/05/18] +\RequirePackage{fontspec}[2010/10/25] \RequirePackage{catchfile} +\RequirePackage{trimspaces} +\RequirePackage{fix-cm} % avoid some warnings +\RequirePackage{filehook}[2011/01/03] % \end{macrocode} % % Start using \LaTeX3 --- finally! % \begin{macrocode} \ExplSyntaxOn -\@ifclassloaded{memoir}{ - \cs_set_eq:NN \um_after_pkg:nn \AtEndPackage -}{ - \RequirePackage{scrlfile} - \cs_set_eq:NN \um_after_pkg:nn \AfterPackage -} % \end{macrocode} % % \paragraph{Extra \pkg{expl3} variants} @@ -1056,12 +1077,18 @@ This work is "author-maintained" by Will Robertson. % % % \paragraph{Conditionals} +% Engine capabilities: +% \begin{macrocode} +\bool_new:N \c_um_have_fixed_accents_bool +\bool_set:Nn \c_um_have_fixed_accents_bool { + \c_luatex_is_engine_bool && \int_compare_p:n { \luatexversion > 64 } +} +% \end{macrocode} % \begin{macrocode} -\bool_new:N \l_um_fontspec_feature_bool \bool_new:N \l_um_ot_math_bool \bool_new:N \l_um_init_bool \bool_new:N \l_um_implicit_alph_bool -\bool_new:N \g_um_mainfont_set_bool +\bool_new:N \g_um_mainfont_already_set_bool % \end{macrocode} % For \opt{math-style}: % \begin{macrocode} @@ -1091,6 +1118,7 @@ This work is "author-maintained" by Will Robertson. \bool_new:N \g_um_literal_Nabla_bool \bool_new:N \g_um_literal_partial_bool \bool_new:N \g_um_texgreek_bool +\bool_gset_true:N \g_um_texgreek_bool \bool_new:N \l_um_smallfrac_bool \bool_new:N \g_um_literal_colon_bool % \end{macrocode} @@ -1112,10 +1140,10 @@ This work is "author-maintained" by Will Robertson. % \subsection{Extras} % % \begin{macro}{\um_glyph_if_exist:nTF} -%: TODO: Generalise for arbitrary fonts! \cs{\l_um_font} is not always the one used for a specific glyph!! +%: TODO: Generalise for arbitrary fonts! \cs{l_um_font} is not always the one used for a specific glyph!! % \begin{macrocode} \prg_new_conditional:Nnn \um_glyph_if_exist:n {p,TF,T,F} { - \etex_iffontchar:D \l_um_font #1 \scan_stop: + \iffontchar \l_um_font #1 \scan_stop: \prg_return_true: \else: \prg_return_false: @@ -1857,6 +1885,7 @@ This work is "author-maintained" by Will Robertson. } % \end{macrocode} % +% % \paragraph{Nabla and partial} % \begin{macrocode} \keys_define:nn {unicode-math} { @@ -2078,6 +2107,12 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % \end{macro} % +% \begin{macrocode} +\edef\mathfence{\string\mathfence} +\edef\mathover{\string\mathover} +\edef\mathunder{\string\mathunder} +% \end{macrocode} +% % % \begin{macro}{\um_set_big_operator:nnn} % \darg{Symbol font name} @@ -2131,6 +2166,9 @@ This work is "author-maintained" by Will Robertson. % \begin{macro}{\um_radical:nn} % \begin{macro}{\um_delimiter:Nnn} % \begin{macro}{\um_accent:Nnn} +% \begin{macro}{\um_wide_top_accent:Nnn} +% \begin{macro}{\um_wide_bottom_accent:Nnn} +% \begin{macro}{\um_accent_keyword:} % These are all wrappers for the primitive commands that take numerical % input only. % \begin{macrocode} @@ -2155,8 +2193,25 @@ This work is "author-maintained" by Will Robertson. \cs_new:Npn \um_delimiter:Nnn #1#2#3 { \Udelimiter \mathchar@type#1 \csname sym#2\endcsname #3 \scan_stop: } -\cs_new:Npn \um_accent:Nnn #1#2#3 { +\xetex_or_luatex:nnn { \cs_new:Npn \um_accent:Nnn #1#2#3 } { \Umathaccent \mathchar@type#1 \csname sym#2\endcsname #3 \scan_stop: +} { + \Umathaccent \um_accent_keyword: \mathchar@type#1 \csname sym#2\endcsname #3 \scan_stop: +} +\luatex_if_engine:T { + \cs_new_nopar:Npn \um_wide_top_accent:Nnn #1 #2 #3 { + \Umathaccent \mathchar@type #1 \use:c { sym #2 } #3 \scan_stop: + } + \bool_if:NTF \c_um_have_fixed_accents_bool { + \cs_new_nopar:Npn \um_wide_bottom_accent:Nnn #1 #2 #3 { + \Umathaccent bottom~ \mathchar@type #1 \use:c { sym #2 } #3 \scan_stop: + } + \cs_new_protected_nopar:Npn \um_accent_keyword: { + \bool_if:NF \l_um_growing_accents_bool { fixed~ } + } + } { + \cs_new_nopar:Npn \um_accent_keyword: { } + } } % \end{macrocode} % @@ -2171,6 +2226,9 @@ This work is "author-maintained" by Will Robertson. % \end{macro} % \end{macro} % \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} % % % \begin{macro}{\um_overbrace:nnn} @@ -2299,14 +2357,60 @@ This work is "author-maintained" by Will Robertson. \cs_set_eq:NN \um_assign_delcode:nn \um_assign_delcode_parse:nn } % \end{macrocode} -% Now defined |\um_symfont_tl| as the \LaTeX\ math font to access everything: +% Now define |\um_symfont_tl| as the \LaTeX\ math font to access everything: % \begin{macrocode} \DeclareSymbolFont{\um_symfont_tl} {\encodingdefault}{\zf@family}{\mddefault}{\updefault} - \bool_if:nT {\l_um_ot_math_bool && !\g_um_mainfont_set_bool} { - \bool_set_true:N \g_um_mainfont_set_bool + + \bool_if:nT {\l_um_ot_math_bool && !\g_um_mainfont_already_set_bool} { + \bool_set_true:N \g_um_mainfont_already_set_bool +% \end{macrocode} +% Set the math sizes according to the recommend font parameters: +% \begin{macrocode} + \dim_compare:nF { \fontdimen 10 \l_um_font == 0pt } { + \DeclareMathSizes { \f@size } { \f@size } + { \um_fontdimen_to_percent:nn{10}{\l_um_font}\dimexpr \f@size pt\relax } + { \um_fontdimen_to_percent:nn{11}{\l_um_font}\dimexpr \f@size pt\relax } + } +% \end{macrocode} +% Set defaults for fam2 for legacy compatibility: +% \begin{macrocode} + \fontspec_select:xn {\l_um_font_keyval_tl, + Scale=1.00001, + FontAdjustment={ + \fontdimen8\font= \um_get_fontparam:nn {43} {FractionNumeratorDisplayStyleShiftUp}\relax + \fontdimen9\font= \um_get_fontparam:nn {42} {FractionNumeratorShiftUp}\relax + \fontdimen10\font=\um_get_fontparam:nn {32} {StackTopShiftUp}\relax + \fontdimen11\font=\um_get_fontparam:nn {45} {FractionDenominatorDisplayStyleShiftDown}\relax + \fontdimen12\font=\um_get_fontparam:nn {44} {FractionDenominatorShiftDown}\relax + \fontdimen13\font=\um_get_fontparam:nn {21} {SuperscriptShiftUp}\relax + \fontdimen14\font=\um_get_fontparam:nn {21} {SuperscriptShiftUp}\relax + \fontdimen15\font=\um_get_fontparam:nn {22} {SuperscriptShiftUpCramped}\relax + \fontdimen16\font=\um_get_fontparam:nn {18} {SubscriptShiftDown}\relax + \fontdimen17\font=\um_get_fontparam:nn {18} {SubscriptShiftDownWithSuperscript}\relax + \fontdimen18\font=\um_get_fontparam:nn {24} {SuperscriptBaselineDropMax}\relax + \fontdimen19\font=\um_get_fontparam:nn {20} {SubscriptBaselineDropMin}\relax + \fontdimen20\font=0pt\relax % delim1 = FractionDelimiterDisplaySize + \fontdimen21\font=0pt\relax % delim2 = FractionDelimiterSize + \fontdimen22\font=\um_get_fontparam:nn {15} {AxisHeight}\relax + } + } {#2} \DeclareSymbolFont{symbols} {\encodingdefault}{\zf@family}{\mddefault}{\updefault} +% \end{macrocode} +% Set defaults for fam3 for legacy compatibility: +% \begin{macrocode} + \fontspec_select:xn {\l_um_font_keyval_tl, + Scale=0.99999, + FontAdjustment={ + \fontdimen8\font= \um_get_fontparam:nn {48} {FractionRuleThickness}\relax + \fontdimen9\font= \um_get_fontparam:nn {28} {UpperLimitGapMin}\relax + \fontdimen10\font=\um_get_fontparam:nn {30} {LowerLimitGapMin}\relax + \fontdimen11\font=\um_get_fontparam:nn {29} {UpperLimitBaselineRiseMin}\relax + \fontdimen12\font=\um_get_fontparam:nn {31} {LowerLimitBaselineDropMin}\relax + \fontdimen13\font=0pt\relax + } + } {#2} \DeclareSymbolFont{largesymbols} {\encodingdefault}{\zf@family}{\mddefault}{\updefault} } @@ -2319,12 +2423,14 @@ This work is "author-maintained" by Will Robertson. % \begin{itemize} % \item Remap symbols that don't take their natural mathcode % \item Activate any symbols that need to be math-active +% \item Enable wide/narrow accents % \item Assign delimiter codes for symbols that need to grow % \item Setup the maths alphabets (\cs{mathbf} etc.) % \end{itemize} % \begin{macrocode} \um_remap_symbols: \um_setup_mathactives: + \um_setup_accents: \um_setup_delcodes: \um_setup_alphabets: % \end{macrocode} @@ -2336,10 +2442,18 @@ This work is "author-maintained" by Will Robertson. % \end{macro} % % +% \begin{macrocode} +\xetex_or_luatex:nnn { \cs_new:Nn \um_get_fontparam:nn } { + \the\fontdimen#1\zf@basefont\relax +}{ + \directlua{fontspec.mathfontdimen("zf@basefont","#2")} +} +% \end{macrocode} +% % \begin{macro}{\resetmathfont} % \begin{macrocode} \DeclareDocumentCommand \resetmathfont { O{} m } { - \bool_set_false:N \g_um_mainfont_set_bool + \bool_set_false:N \g_um_mainfont_already_set_bool \setmathfont[#1]{#2} } % \end{macrocode} @@ -2350,28 +2464,25 @@ This work is "author-maintained" by Will Robertson. % Select the font with \cs{fontspec} and define \cs{l_um_font} from it. % \begin{macrocode} \cs_new:Npn \um_fontspec_select_font:n #1 { - \bool_set_true:N \l_um_fontspec_feature_bool - \fontspec_select:xn - { - \luatex_if_engine:T { Renderer = Basic, } - BoldFont = {}, ItalicFont = {}, - Script = Math, - SizeFeatures = { - {Size = \tf@size-} , - {Size = \sf@size-\tf@size , - Font = \l_um_script_font_tl , - \l_um_script_features_tl - } , - {Size = -\sf@size , - Font = \l_um_sscript_font_tl , - \l_um_sscript_features_tl - } - }, - \l_um_unknown_keys_clist - } - {#1} + \tl_set:Nx \l_um_font_keyval_tl { + \luatex_if_engine:T { Renderer = Basic, } + BoldFont = {}, ItalicFont = {}, + Script = Math, + SizeFeatures = { + {Size = \tf@size-} , + {Size = \sf@size-\tf@size , + Font = \l_um_script_font_tl , + \l_um_script_features_tl + } , + {Size = -\sf@size , + Font = \l_um_sscript_font_tl , + \l_um_sscript_features_tl + } + }, + \l_um_unknown_keys_clist + } + \fontspec_select:xn {\l_um_font_keyval_tl} {#1} \tl_set_eq:NN \l_um_font \zf@basefont - \bool_set_false:N \l_um_fontspec_feature_bool } % \end{macrocode} % \end{macro} @@ -2603,7 +2714,7 @@ This work is "author-maintained" by Will Robertson. % % Also, what about right-to-left square roots? % -% \begin{macro}{\um@radicals} +% \begin{macro}{\l_um_radicals_tl} % We organise radicals in the same way as nolimits-operators; that is, % in a comma-list. % \begin{macrocode} @@ -2611,53 +2722,272 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % \end{macro} % -% \subsection{Delimiters} -% \begin{macro}{\left} -% We redefine the primitive to be preceded by \cmd\mathopen; -% this gives much better spacing in cases such as \cmd\sin\cmd\left\dots. -% Courtesy of Frank Mittelbach:\par -% {\small\url{http://www.latex-project.org/cgi-bin/ltxbugs2html?pr=latex/3853&prlatex/3754}} +% \subsection{Maths accents} +% +% Maths accents should just work \emph{if they are available in the font}. +% +% \subsection{Common interface for font parameters} +% +% \XeTeX\ and \LuaTeX\ have different interfaces for math font parameters. +% We use \LuaTeX’s interface because it’s much better, but rename the primitives to be more \LaTeX3-like. +% There are getter and setter commands for each font parameter. +% The names of the parameters is derived from the \LuaTeX\ names, with underscores inserted between words. +% For every parameter \cs{Umath\meta{\LuaTeX\ name}}, we define an expandable getter command \cs{um_\meta{\LaTeX3 name}:N} and a protected setter command \cs{um_set_\meta{\LaTeX3 name}:Nn}. +% The getter command takes one of the style primitives (\cs{displaystyle} etc.)\ and expands to the font parameter, which is a \meta{dimension}. +% The setter command takes a style primitive and a dimension expression, which is parsed with \cs{dim_eval:n}. +% +% Often, the mapping between font dimensions and font parameters is bijective, but there are cases which require special attention: +% \begin{itemize} +% \item Some parameters map to different dimensions in display and non-display styles. +% \item Likewise, one parameter maps to different dimensions in non-cramped and cramped styles. +% \item There are a few parameters for which \XeTeX\ doesn’t seem to provide \cs{fontdimen}s; in this case the getter and setter commands are left undefined. +% \end{itemize} +% +% \paragraph{Cramped style tokens} +% \LuaTeX\ has \cs{crampeddisplaystyle} etc.,\ but they are loaded as \cs{luatexcrampeddisplaystyle} etc.\ by the \pkg{luatextra} package. +% \XeTeX, however, doesn’t have these primitives, and their syntax cannot really be emulated. +% Nevertheless, we define these commands as quarks, so they can be used as arguments to the font parameter commands (but nowhere else). +% Making these commands available is necessary because we need to make a distinction between cramped and non-cramped styles for one font parameter. +% +% \begin{macro}{\um_new_cramped_style:N} +% \darg{command} +% Define \meta{command} as a new cramped style switch. +% For \LuaTeX, simply rename the correspronding primitive. +% For \XeTeX, define \meta{command} as a new quark. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \um_new_cramped_style:N #1 { + \xetex_or_luatex:nn { + \quark_new:N #1 + } { + \cs_new_eq:Nc #1 { luatex \cs_to_str:N #1 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\crampeddisplaystyle} +% \begin{macro}{\crampedtextstyle} +% \begin{macro}{\crampedscriptstyle} +% \begin{macro}{\crampedscriptscriptstyle} +% The cramped style commands. % \begin{macrocode} -\let\left@primitive\left -\def\left{\mathopen{}\left@primitive} +\um_new_cramped_style:N \crampeddisplaystyle +\um_new_cramped_style:N \crampedtextstyle +\um_new_cramped_style:N \crampedscriptstyle +\um_new_cramped_style:N \crampedscriptscriptstyle % \end{macrocode} % \end{macro} -% No re-definition is made for \cmd\right\ because it's not -% necessary. +% \end{macro} +% \end{macro} +% \end{macro} % -% \subsection{Maths accents} +% \paragraph{Font dimension mapping} +% Font parameters may differ between the styles. +% \LuaTeX\ accounts for this by having the parameter primitives take a style token argument. +% To replicate this behavior in \XeTeX, we have to map style tokens to specific combinations of font dimension numbers and math fonts (\cs{textfont} etc.). +% +% \begin{macro}{\um_font_dimen:Nnnnn} +% \darg{style token} +% \darg{font dimen for display style} +% \darg{font dimen for cramped display style} +% \darg{font dimen for non-display styles} +% \darg{font dimen for cramped non-display styles} +% Map math style to \XeTeX\ math font dimension. +% \meta{style token} must be one of the style switches (\cs{displaystyle}, \cs{crampeddisplaystyle}, \dots). +% The other parameters are integer constants referring to font dimension numbers. +% The macro expands to a dimension which contains the appropriate font dimension. +% \begin{macrocode} +\xetex_if_engine:T { + \cs_new_nopar:Npn \um_font_dimen:Nnnnn #1 #2 #3 #4 #5 { + \fontdimen + \cs_if_eq:NNTF #1 \displaystyle { + #2 \textfont + } { + \cs_if_eq:NNTF #1 \crampeddisplaystyle { + #3 \textfont + } { + \cs_if_eq:NNTF #1 \textstyle { + #4 \textfont + } { + \cs_if_eq:NNTF #1 \crampedtextstyle { + #5 \textfont + } { + \cs_if_eq:NNTF #1 \scriptstyle { + #4 \scriptfont + } { + \cs_if_eq:NNTF #1 \crampedscriptstyle { + #5 \scriptfont + } { + \cs_if_eq:NNTF #1 \scriptscriptstyle { + #4 \scriptscriptfont + } { +% \end{macrocode} +% Should we check here if the style is invalid? +% \begin{macrocode} + #5 \scriptscriptfont + } + } + } + } + } + } + } +% \end{macrocode} +% Which family to use? +% \begin{macrocode} + \c_two + } +} +% \end{macrocode} +% \end{macro} % -% Maths accents should just work \emph{if they are available in the font}. +% \paragraph{Font parameters} +% This paragraph contains macros for defining the font parameter interface, as well as the definition for all font parameters known to \LuaTeX. +% +% \begin{macro}{\um_font_param:nnnnn} +% \darg{name} +% \darg{font dimension for non-cramped display style} +% \darg{font dimension for cramped display style} +% \darg{font dimension for non-cramped non-display styles} +% \darg{font dimension for cramped non-display styles} +% This macro defines getter and setter functions for the font parameter \meta{name}. +% The \LuaTeX\ font parameter name is produced by removing all underscores and prefixing the result with |luatexUmath|. +% The \XeTeX\ font dimension numbers must be integer constants. +% \begin{macrocode} +\xetex_or_luatex:nnn { + \cs_new_protected_nopar:Npn \um_font_param:nnnnn #1 #2 #3 #4 #5 +} { + \um_font_param_aux:ccnnnn { um_ #1 :N } { um_set_ #1 :N } + { #2 } { #3 } { #4 } { #5 } +} { + \tl_set:Nn \l_um_tmpa_tl { #1 } + \tl_remove_all_in:Nn \l_um_tmpa_tl { _ } + \um_font_param_aux:ccc { um_ #1 :N } { um_set_ #1 :N } + { luatexUmath \l_um_tmpa_tl } +} +% \end{macrocode} +% \end{macro} % -% \section{Font features} +% \begin{macro}{\um_font_param:nnn} +% \darg{name} +% \darg{font dimension for display style} +% \darg{font dimension for non-display styles} +% This macro defines getter and setter functions for the font parameter \meta{name}. +% The \LuaTeX\ font parameter name is produced by removing all underscores and prefixing the result with |luatexUmath|. +% The \XeTeX\ font dimension numbers must be integer constants. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \um_font_param:nnn #1 #2 #3 { + \um_font_param:nnnnn { #1 } { #2 } { #2 } { #3 } { #3 } +} +% \end{macrocode} +% \end{macro} % -% \begin{macro}{\um@zf@feature} -% Use the same method as \pkg{fontspec} for feature definition -% (\ie, using \pkg{xkeyval}) but with a conditional to restrict -% the scope of these features to \pkg{unicode-math} commands. +% \begin{macro}{\um_font_param:nn} +% \darg{name} +% \darg{font dimension} +% This macro defines getter and setter functions for the font parameter \meta{name}. +% The \LuaTeX\ font parameter name is produced by removing all underscores and prefixing the result with |luatexUmath|. +% The \XeTeX\ font dimension number must be an integer constant. % \begin{macrocode} -\newcommand\um@zf@feature[2]{ - \define@key[zf]{options}{#1}[]{ - \bool_if:NTF \l_um_fontspec_feature_bool { - #2 - }{ - \um_warning:n {maths-feature-only} +\cs_new_protected_nopar:Npn \um_font_param:nn #1 #2 { + \um_font_param:nnnnn { #1 } { #2 } { #2 } { #2 } { #2 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\um_font_param:n} +% \darg{name} +% This macro defines getter and setter functions for the font parameter \meta{name}, which is considered unavailable in \XeTeX\@. +% The \LuaTeX\ font parameter name is produced by removing all underscores and prefixing the result with |luatexUmath|. +% \begin{macrocode} +\xetex_or_luatex:nnn { + \cs_new_protected_nopar:Npn \um_font_param:n #1 +} { } { + \um_font_param:nnnnn { #1 } { 0 } { 0 } { 0 } { 0 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\um_font_param_aux:NNnnnn} +% \begin{macro}{\um_font_param_aux:NNN} +% Auxiliary macros for generating font parameter accessor macros. +% \begin{macrocode} +\xetex_or_luatex:nn { + \cs_new_protected_nopar:Npn \um_font_param_aux:NNnnnn #1 #2 #3 #4 #5 #6 { + \cs_new_nopar:Npn #1 ##1 { + \um_font_dimen:Nnnnn ##1 { #3 } { #4 } { #5 } { #6 } + } + \cs_new_protected_nopar:Npn #2 ##1 ##2 { + #1 ##1 \dim_eval:n { ##2 } } } + \cs_generate_variant:Nn \um_font_param_aux:NNnnnn { cc } +} { + \cs_new_protected_nopar:Npn \um_font_param_aux:NNN #1 #2 #3 { + \cs_new_nopar:Npn #1 ##1 { + #3 ##1 + } + \cs_new_protected_nopar:Npn #2 ##1 ##2 { + #3 ##1 \dim_eval:n { ##2 } + } + } + \cs_generate_variant:Nn \um_font_param_aux:NNN { ccc } } % \end{macrocode} % \end{macro} +% \end{macro} % -% \subsection{OpenType maths font features} -% \begin{macrocode} -\xetex_or_luatex:nnn { \um@zf@feature {ScriptStyle} } - { \fontspec_update_featstr:n {+ssty=0} } - { \fontspec_update_featstr:n {+ssty=1} } -\xetex_or_luatex:nnn { \um@zf@feature {ScriptScriptStyle} } - { \fontspec_update_featstr:n {+ssty=1} } - { \fontspec_update_featstr:n {+ssty=2} } +% Now all font parameters that are listed in the \LuaTeX\ reference follow. +% \begin{macrocode} +\um_font_param:nn { axis } { 15 } +\um_font_param:nn { operator_size } { 13 } +\um_font_param:n { fraction_del_size } +\um_font_param:nnn { fraction_denom_down } { 45 } { 44 } +\um_font_param:nnn { fraction_denom_vgap } { 50 } { 49 } +\um_font_param:nnn { fraction_num_up } { 43 } { 42 } +\um_font_param:nnn { fraction_num_vgap } { 47 } { 46 } +\um_font_param:nn { fraction_rule } { 48 } +\um_font_param:nn { limit_above_bgap } { 29 } +\um_font_param:n { limit_above_kern } +\um_font_param:nn { limit_above_vgap } { 28 } +\um_font_param:nn { limit_below_bgap } { 31 } +\um_font_param:n { limit_below_kern } +\um_font_param:nn { limit_below_vgap } { 30 } +\um_font_param:nn { over_delimiter_vgap } { 41 } +\um_font_param:nn { over_delimiter_bgap } { 38 } +\um_font_param:nn { under_delimiter_vgap } { 40 } +\um_font_param:nn { under_delimiter_bgap } { 39 } +\um_font_param:nn { overbar_kern } { 55 } +\um_font_param:nn { overbar_rule } { 54 } +\um_font_param:nn { overbar_vgap } { 53 } +\um_font_param:n { quad } +\um_font_param:nn { radical_kern } { 62 } +\um_font_param:nn { radical_rule } { 61 } +\um_font_param:nnn { radical_vgap } { 60 } { 59 } +\um_font_param:nn { radical_degree_before } { 63 } +\um_font_param:nn { radical_degree_after } { 64 } +\um_font_param:nn { radical_degree_raise } { 65 } +\um_font_param:nn { space_after_script } { 27 } +\um_font_param:nnn { stack_denom_down } { 35 } { 34 } +\um_font_param:nnn { stack_num_up } { 33 } { 32 } +\um_font_param:nnn { stack_vgap } { 37 } { 36 } +\um_font_param:nn { sub_shift_down } { 18 } +\um_font_param:nn { sub_shift_drop } { 20 } +\um_font_param:n { subsup_shift_down } +\um_font_param:nn { sub_top_max } { 19 } +\um_font_param:nn { subsup_vgap } { 25 } +\um_font_param:nn { sup_bottom_min } { 23 } +\um_font_param:nn { sup_shift_drop } { 24 } +\um_font_param:nnnnn { sup_shift_up } { 21 } { 22 } { 21 } { 22 } +\um_font_param:nn { supsub_bottom_max } { 26 } +\um_font_param:nn { underbar_kern } { 58 } +\um_font_param:nn { underbar_rule } { 57 } +\um_font_param:nn { underbar_vgap } { 56 } +\um_font_param:n { connector_overlap_min } % \end{macrocode} % +% \section{Font features} +% % \subsection{Script and scriptscript font options} % \begin{macrocode} \keys_define:nn {unicode-math} @@ -3150,12 +3480,13 @@ This work is "author-maintained" by Will Robertson. % First check that at least one of the alphabets for the font shape is defined\dots % \begin{macrocode} \clist_map_inline:nn {#2} { - \cs_if_exist:cT {um_config_ \l_um_style_tl _##1:n} { - \str_if_eq:nnTF {##1}{misc} { + \tl_set:Nx \l_um_tmpa_tl { \trim@spaces {##1} } + \cs_if_exist:cT {um_config_ \l_um_style_tl _\l_um_tmpa_tl :n} { + \str_if_eq:xxTF {\l_um_tmpa_tl}{misc} { \um_maybe_init_alphabet:V \l_um_style_tl \clist_map_break: }{ - \um_glyph_if_exist:cT { \um_to_usv:nn {#3}{##1} }{ + \um_glyph_if_exist:cT { \um_to_usv:nn {#3}{\l_um_tmpa_tl} }{ \um_maybe_init_alphabet:V \l_um_style_tl \clist_map_break: } @@ -3166,22 +3497,23 @@ This work is "author-maintained" by Will Robertson. % \dots and then loop through them defining the individual ranges: % \begin{macrocode} \clist_map_inline:nn {#2} { - \cs_if_exist:cT {um_config_ \l_um_style_tl _##1:n} { - \str_if_eq:nnTF {##1}{misc} { - \um_trace:nx {setup-alph} {math \l_um_style_tl~(##1)} - \use:c {um_config_ \l_um_style_tl _##1:n} {#3} + \tl_set:Nx \l_um_tmpa_tl { \trim@spaces {##1} } + \cs_if_exist:cT {um_config_ \l_um_style_tl _ \l_um_tmpa_tl :n} { + \str_if_eq:xxTF {\l_um_tmpa_tl}{misc} { + \um_trace:nx {setup-alph} {math \l_um_style_tl~(\l_um_tmpa_tl)} + \use:c {um_config_ \l_um_style_tl _ \l_um_tmpa_tl :n} {#3} }{ - \um_glyph_if_exist:cTF { \um_to_usv:nn {#3}{##1} } { - \um_trace:nx {setup-alph} {math \l_um_style_tl~(##1)} - \use:c {um_config_ \l_um_style_tl _##1:n} {#3} + \um_glyph_if_exist:cTF { \um_to_usv:nn {#3}{\l_um_tmpa_tl} } { + \um_trace:nx {setup-alph} {math \l_um_style_tl~(\l_um_tmpa_tl)} + \use:c {um_config_ \l_um_style_tl _ \l_um_tmpa_tl :n} {#3} }{ \bool_if:NTF \l_um_implicit_alph_bool { \seq_put_right:Nx \l_um_missing_alph_seq { \@backslashchar math \l_um_style_tl \space - (\tl_use:c{g_um_math_alphabet_name_##1_tl}) + (\tl_use:c{g_um_math_alphabet_name_ \l_um_tmpa_tl _tl}) } }{ - \use:c {um_config_ \l_um_style_tl _##1:n} {up} + \use:c {um_config_ \l_um_style_tl _ \l_um_tmpa_tl :n} {up} } } } @@ -4166,9 +4498,6 @@ This work is "author-maintained" by Will Robertson. % \begin{macrocode} \xetex_or_luatex:nnn { \cs_set:Npn \um_symbol_setup: } { - \def\mathfence{\mathfence} - \def\mathover{\mathover} - \def\mathunder{\mathunder} \cs_set:Npn \UnicodeMathSymbol ##1##2##3##4 { \prg_case_tl:Nnn ##3 { \mathover {} \mathunder {} } { @@ -4254,16 +4583,17 @@ This work is "author-maintained" by Will Robertson. % Ensure catcodes are appropriate; % make sure |#| is an `other' so that we don't get confused with \cs{mathoctothorpe}. % \begin{macrocode} -\AtBeginDocument{ +\AtBeginDocument{\um_define_math_chars:} +\cs_set:Nn \um_define_math_chars: { \group_begin: \char_make_math_superscript:N \^ - \cs_set:Npn \_um_sym:nnn #1#2#3 { - \bool_if:nF { \cs_if_eq_p:NN #3 \mathaccent || - \cs_if_eq_p:NN #3 \mathopen || - \cs_if_eq_p:NN #3 \mathclose || - \cs_if_eq_p:NN #3 \mathover || - \cs_if_eq_p:NN #3 \mathunder } { - \um_cs_set_eq_active_char:Nw #2 = #1 \q_nil \ignorespaces + \cs_set:Npn \_um_sym:nnn ##1##2##3 { + \bool_if:nF { \cs_if_eq_p:NN ##3 \mathaccent || + \cs_if_eq_p:NN ##3 \mathopen || + \cs_if_eq_p:NN ##3 \mathclose || + \cs_if_eq_p:NN ##3 \mathover || + \cs_if_eq_p:NN ##3 \mathunder } { + \um_cs_set_eq_active_char:Nw ##2 = ##1 \q_nil \ignorespaces } } \char_make_other:N \# @@ -4285,7 +4615,7 @@ This work is "author-maintained" by Will Robertson. } |group_end: % \end{macrocode} -% Fix \cs{backslash}: +% Fix \cs{backslash}: ^^A | % \begin{macrocode} % \end{macrocode} % @@ -4409,18 +4739,38 @@ This work is "author-maintained" by Will Robertson. % % \begin{macrocode} \cs_new:Npn \um_scan_prime: { + \cs_set_eq:NN \um_superscript:n \use:n \int_zero:N \l_um_primecount_int \um_scanprime_collect:N \um_prime_single_mchar } \cs_new:Npn \um_scan_dprime: { + \cs_set_eq:NN \um_superscript:n \use:n \int_set:Nn \l_um_primecount_int {1} \um_scanprime_collect:N \um_prime_single_mchar } \cs_new:Npn \um_scan_trprime: { + \cs_set_eq:NN \um_superscript:n \use:n \int_set:Nn \l_um_primecount_int {2} \um_scanprime_collect:N \um_prime_single_mchar } \cs_new:Npn \um_scan_qprime: { + \cs_set_eq:NN \um_superscript:n \use:n + \int_set:Nn \l_um_primecount_int {3} + \um_scanprime_collect:N \um_prime_single_mchar +} +\cs_new:Npn \um_scan_sup_prime: { + \int_zero:N \l_um_primecount_int + \um_scanprime_collect:N \um_prime_single_mchar +} +\cs_new:Npn \um_scan_sup_dprime: { + \int_set:Nn \l_um_primecount_int {1} + \um_scanprime_collect:N \um_prime_single_mchar +} +\cs_new:Npn \um_scan_sup_trprime: { + \int_set:Nn \l_um_primecount_int {2} + \um_scanprime_collect:N \um_prime_single_mchar +} +\cs_new:Npn \um_scan_sup_qprime: { \int_set:Nn \l_um_primecount_int {3} \um_scanprime_collect:N \um_prime_single_mchar } @@ -4471,14 +4821,29 @@ This work is "author-maintained" by Will Robertson. } } \cs_new:Npn \um_scan_backprime: { + \cs_set_eq:NN \um_superscript:n \use:n \int_zero:N \l_um_primecount_int \um_scanbackprime_collect:N \um_backprime_single_mchar } \cs_new:Npn \um_scan_backdprime: { + \cs_set_eq:NN \um_superscript:n \use:n \int_set:Nn \l_um_primecount_int {1} \um_scanbackprime_collect:N \um_backprime_single_mchar } \cs_new:Npn \um_scan_backtrprime: { + \cs_set_eq:NN \um_superscript:n \use:n + \int_set:Nn \l_um_primecount_int {2} + \um_scanbackprime_collect:N \um_backprime_single_mchar +} +\cs_new:Npn \um_scan_sup_backprime: { + \int_zero:N \l_um_primecount_int + \um_scanbackprime_collect:N \um_backprime_single_mchar +} +\cs_new:Npn \um_scan_sup_backdprime: { + \int_set:Nn \l_um_primecount_int {1} + \um_scanbackprime_collect:N \um_backprime_single_mchar +} +\cs_new:Npn \um_scan_sup_backtrprime: { \int_set:Nn \l_um_primecount_int {2} \um_scanbackprime_collect:N \um_backprime_single_mchar } @@ -4521,14 +4886,15 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % % \begin{macrocode} -\AtBeginDocument { - \cs_set_eq:NN \prime \um_scan_prime: - \cs_set_eq:NN \drime \um_scan_dprime: - \cs_set_eq:NN \trprime \um_scan_trprime: - \cs_set_eq:NN \qprime \um_scan_qprime: - \cs_set_eq:NN \backprime \um_scan_backprime: - \cs_set_eq:NN \backdprime \um_scan_backdprime: - \cs_set_eq:NN \backtrprime \um_scan_backtrprime: +\AtBeginDocument{\um_define_prime_commands: \um_define_prime_chars:} +\cs_set:Nn \um_define_prime_commands: { + \cs_set_eq:NN \prime \um_prime_single_mchar + \cs_set_eq:NN \drime \um_prime_double_mchar + \cs_set_eq:NN \trprime \um_prime_triple_mchar + \cs_set_eq:NN \qprime \um_prime_quad_mchar + \cs_set_eq:NN \backprime \um_backprime_single_mchar + \cs_set_eq:NN \backdprime \um_backprime_double_mchar + \cs_set_eq:NN \backtrprime \um_backprime_triple_mchar } \group_begin: \char_make_active:N \' @@ -4540,56 +4906,73 @@ This work is "author-maintained" by Will Robertson. \char_make_active:n {"2035} \char_make_active:n {"2036} \char_make_active:n {"2037} - \AtBeginDocument{ - \cs_set_eq:NN ' \um_scan_prime: - \cs_set_eq:NN ^^^^2032 \um_scan_prime: - \cs_set_eq:NN ^^^^2033 \um_scan_dprime: - \cs_set_eq:NN ^^^^2034 \um_scan_trprime: - \cs_set_eq:NN ^^^^2057 \um_scan_qprime: - \cs_set_eq:NN ` \um_scan_backprime: - \cs_set_eq:NN ^^^^2035 \um_scan_backprime: - \cs_set_eq:NN ^^^^2036 \um_scan_backdprime: - \cs_set_eq:NN ^^^^2037 \um_scan_backtrprime: + \cs_gset:Nn \um_define_prime_chars: { + \cs_set_eq:NN ' \um_scan_sup_prime: + \cs_set_eq:NN ^^^^2032 \um_scan_sup_prime: + \cs_set_eq:NN ^^^^2033 \um_scan_sup_dprime: + \cs_set_eq:NN ^^^^2034 \um_scan_sup_trprime: + \cs_set_eq:NN ^^^^2057 \um_scan_sup_qprime: + \cs_set_eq:NN ` \um_scan_sup_backprime: + \cs_set_eq:NN ^^^^2035 \um_scan_sup_backprime: + \cs_set_eq:NN ^^^^2036 \um_scan_sup_backdprime: + \cs_set_eq:NN ^^^^2037 \um_scan_sup_backtrprime: } \group_end: % \end{macrocode} % % \subsection{Unicode radicals} % -% -% \begin{macro}{\sqrt} -% Redefine this macro for \LuaTeX, which provides us a nice primitive to use. % \begin{macrocode} -\luatex_if_engine:T { - \RenewDocumentCommand \sqrt { O{} m } { - \luatexUroot \l_um_radical_sqrt_tl {#1} {#2} - } - \cs_set:Npn \root #1 \of #2 { - \luatexUroot \l_um_radical_sqrt_tl {#1} {#2} - } -} +\AtBeginDocument{\um_redefine_radical:} +\xetex_or_luatex:nnn { \cs_set:Nn \um_redefine_radical: } { + \@ifpackageloaded { amsmath } { } { % \end{macrocode} -% \end{macro} -% -% % \begin{macro}{\r@@t} % \darg{A mathstyle (for \cmd\mathpalette)} % \darg{Leading superscript for the sqrt sign} % A re-implementation of \LaTeX's hard-coded n-root sign using the appropriate \cmd\fontdimen s. % \begin{macrocode} -\cs_set_nopar:Npn \r@@t #1#2 { - \setbox\z@\hbox{$\m@th #1\sqrtsign{#2}$} - \um_mathstyle_scale:Nnn{#1}{\kern}{\fontdimen63\l_um_font} - \raise \dimexpr( - \um_fontdimen_to_percent:nn{65}{\l_um_font}\ht\z@- - \um_fontdimen_to_percent:nn{65}{\l_um_font}\dp\z@ - )\relax - \copy \rootbox - \um_mathstyle_scale:Nnn{#1}{\kern}{\fontdimen64\l_um_font} - \box \z@ -} + \cs_set_nopar:Npn \r@@t ##1 ##2 { + \hbox_set:Nn \l_tmpa_box { + \c_math_shift_token + \m@th + ##1 + \sqrtsign { ##2 } + \c_math_shift_token + } + \um_mathstyle_scale:Nnn ##1 { \kern } { + \fontdimen 63 \l_um_font + } + \box_move_up:nn { + (\box_ht:N \l_tmpa_box - \box_dp:N \l_tmpa_box) + * \number \fontdimen 65 \l_um_font / 100 + } { + \box_use:N \rootbox + } + \um_mathstyle_scale:Nnn ##1 { \kern } { + \fontdimen 64 \l_um_font + } + \box_use_clear:N \l_tmpa_box + } % \end{macrocode} % \end{macro} +% \begin{macrocode} + } +} { + \@ifpackageloaded { amsmath } { } { +% \end{macrocode} +% \begin{macro}{\root} +% Redefine this macro for \LuaTeX, which provides us a nice primitive to use. +% \begin{macrocode} + \cs_set:Npn \root ##1 \of ##2 { + \luatexUroot \l_um_radical_sqrt_tl { ##1 } { ##2 } + } +% \end{macrocode} +% \end{macro} +% \begin{macrocode} + } +} +% \end{macrocode} % % % \begin{macro}{\um_fontdimen_to_percent:nn} @@ -4598,7 +4981,7 @@ This work is "author-maintained" by Will Robertson. % \cmd\fontdimen s |10|, |11|, and |65| aren't actually dimensions, they're percentage values given in units of |sp|. This macro takes a font dimension number and outputs the decimal value of the associated parameter. % \begin{macrocode} \cs_new:Npn \um_fontdimen_to_percent:nn #1#2 { - 0.\strip@pt\dimexpr\fontdimen#1#2 *65536\relax + \strip@pt\dimexpr\fontdimen#1#2*65536/100\relax } % \end{macrocode} % \end{macro} @@ -4851,7 +5234,6 @@ This work is "author-maintained" by Will Robertson. % automatically by the maths characters database. % \begin{macrocode} \def\to{\rightarrow} -\def\overrightarrow{\vec} \def\le{\leq} \def\ge{\geq} \def\neq{\ne} @@ -4864,6 +5246,10 @@ This work is "author-maintained" by Will Robertson. \def\diamond{\smwhtdiamond} \def\emptyset{\varnothing} \def\hbar{\hslash} +\def\land{\wedge} +\def\lor{\vee} +\def\owns{\ni} +\def\gets{\leftarrow} % \end{macrocode} % These are somewhat odd: (and their usual Unicode uprightness does not match their amssymb glyphs) % \begin{macrocode} @@ -4900,13 +5286,6 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % \end{macro} % -% \verb|\overline| is a \LuaTeX\ primitive: -% \begin{macrocode} -\luatex_if_engine:T { - \cs_set:Npn \overline {\pdfprimitive\overline} -} -% \end{macrocode} -% % \begin{macro}{\digamma} % \begin{macro}{\Digamma} % I might end up just changing these in the table. @@ -4926,22 +5305,113 @@ This work is "author-maintained" by Will Robertson. \def\operator@font{\um_switchto_mathup:} % \end{macrocode} % -% \begin{macro}{\um_patch_pkg:nn} -% \darg{package} -% \darg{code} -% If \meta{package} is loaded either already or later in the preamble, \meta{code} -% is executed (after the package is loaded in the latter case). +% \begin{macro}{\um_tmpa:w} +% A scratch macro. % \begin{macrocode} -\cs_new:Npn \um_patch_pkg:nn #1#2 { - \@ifpackageloaded {#1} { - #2 - }{ - \um_after_pkg:nn {#1} {#2} +\chk_if_free_cs:N \um_tmpa:w +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\um_check_and_fix:NNnnnn} +% \darg{command} +% \darg{factory command} +% \darg{parameter text} +% \darg{expected replacement text} +% \darg{new replacement text for \LuaTeX} +% \darg{new replacement text for \XeTeX} +% Tries to patch \meta{command}. +% If \meta{command} is undefined, do nothing. +% Otherwise it must be a macro with the given \meta{parameter text} and \meta{expected replacement text}, created by the given \meta{factory command} or equivalent. +% In this case it will be overwritten using the \meta{parameter text} and the \meta{new replacement text for \LuaTeX} or the \meta{new replacement text for \XeTeX}, depending on the engine. +% Otherwise issue a warning and don’t overwrite. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \um_check_and_fix:NNnnnn #1 #2 #3 #4 #5 #6 { + \cs_if_exist:NT #1 { + \token_if_macro:NTF #1 { + \group_begin: + #2 \um_tmpa:w #3 { #4 } + \cs_if_eq:NNTF #1 \um_tmpa:w { + \msg_info:nnx { unicode-math } { patch-macro } + { \token_to_str:N #1 } + \group_end: + \xetex_or_luatex:nnn { #2 #1 #3 } { #6 } { #5 } + } { + \msg_warning:nnxxx { unicode-math } { wrong-meaning } + { \token_to_str:N #1 } { \token_to_meaning:N #1 } + { \token_to_meaning:N \um_tmpa:w } + \group_end: + } + } { + \msg_warning:nnx { unicode-math } { macro-expected } + { \token_to_str:N #1 } + } } } % \end{macrocode} % \end{macro} % +% \begin{macro}{\um_check_and_fix:NNnnn} +% \darg{command} +% \darg{factory command} +% \darg{parameter text} +% \darg{expected replacement text} +% \darg{new replacement text} +% Tries to patch \meta{command}. +% If \meta{command} is undefined, do nothing. +% Otherwise it must be a macro with the given \meta{parameter text} and \meta{expected replacement text}, created by the given \meta{factory command} or equivalent. +% In this case it will be overwritten using the \meta{parameter text} and the \meta{new replacement text}. +% Otherwise issue a warning and don’t overwrite. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \um_check_and_fix:NNnnn #1 #2 #3 #4 #5 { + \um_check_and_fix:NNnnnn #1 #2 { #3 } { #4 } { #5 } { #5 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\um_check_and_fix_luatex:NNnnn} +% \begin{macro}{\um_check_and_fix_luatex:cNnnn} +% \darg{command} +% \darg{factory command} +% \darg{parameter text} +% \darg{expected replacement text} +% \darg{new replacement text} +% Tries to patch \meta{command}. +% If \XeTeX\ is the current engine or \meta{command} is undefined, do nothing. +% Otherwise it must be a macro with the given \meta{parameter text} and \meta{expected replacement text}, created by the given \meta{factory command} or equivalent. +% In this case it will be overwritten using the \meta{parameter text} and the \meta{new replacement text}. +% Otherwise issue a warning and don’t overwrite. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \um_check_and_fix_luatex:NNnnn #1 #2 #3 #4 #5 { + \luatex_if_engine:T { + \um_check_and_fix:NNnnn #1 #2 { #3 } { #4 } { #5 } + } +} +\cs_generate_variant:Nn \um_check_and_fix_luatex:NNnnn { c } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \paragraph{\LaTeXe\ kernel} +% \cs{frac} can be patched for \LuaTeX, but \cs{choose}, \cs{brack} and \cs{brace} should be discouraged. +% Probably these fixes (and the analogous \pkg{amsmath} fixes below) should go into \pkg{luatextra} or a similar \LuaLaTeX\ package. +% \begin{macrocode} +\luatex_if_engine:T { + \AtBeginDocument{\um_patch_amsmath:} + \cs_set:Nn \um_patch_amsmath: { + \@ifpackageloaded { amsmath } { } { + \um_check_and_fix:NNnnn \frac \cs_set_nopar:Npn { ##1 ##2 } { + { + \begingroup ##1 \endgroup \over ##2 + } + } { + { + \luatexUstack { \group_begin: ##1 \group_end: \over ##2 } + } + } + } + } +} +% \end{macrocode} % % \paragraph{\pkg{url}} % Simply need to get \pkg{url} in a state such that @@ -4953,7 +5423,7 @@ This work is "author-maintained" by Will Robertson. % but activates automatically so old documents that might change the \cs{url} % font still work correctly. % \begin{macrocode} -\um_patch_pkg:nn {url} { +\AtEndOfPackageFile * {url} { \tl_put_left:Nn \Url@FormatString { \um_switchto_mathup: } \tl_put_right:Nn \UrlSpecials { \do\`{\mathchar`\`} @@ -4967,7 +5437,7 @@ This work is "author-maintained" by Will Robertson. % \paragraph{\pkg{amsmath}} % Since the mathcode of |`\-| is greater than eight bits, this piece of |\AtBeginDocument| code from \pkg{amsmath} dies if we try and set the maths font in the preamble: % \begin{macrocode} -\um_patch_pkg:nn {amsmath} { +\AtEndOfPackageFile * {amsmath} { \tl_remove_in:Nn \@begindocumenthook { \mathchardef\std@minus\mathcode`\-\relax \mathchardef\std@equal\mathcode`\=\relax @@ -4983,15 +5453,191 @@ This work is "author-maintained" by Will Robertson. % This isn't as clever as the \pkg{amsmath} definition but I think it works: % \begin{macrocode} \def \resetMathstrut@ {% - \setbox\z@\hbox{$($}% + \setbox\z@\hbox{$($}%) \ht\Mathstrutbox@\ht\z@ \dp\Mathstrutbox@\dp\z@ } +% \end{macrocode} +% The |subarray| environment uses inappropriate font dimensions. +% \begin{macrocode} + \um_check_and_fix:NNnnn \subarray \cs_set:Npn { #1 } { + \vcenter + \bgroup + \Let@ + \restore@math@cr + \default@tag + \baselineskip \fontdimen 10~ \scriptfont \tw@ + \advance \baselineskip \fontdimen 12~ \scriptfont \tw@ + \lineskip \thr@@ \fontdimen 8~ \scriptfont \thr@@ + \lineskiplimit \lineskip + \ialign + \bgroup + \ifx c #1 \hfil \fi + $ \m@th \scriptstyle ## $ + \hfil + \crcr + } { + \vcenter + \c_group_begin_token + \Let@ + \restore@math@cr + \default@tag + \skip_set:Nn \baselineskip { +% \end{macrocode} +% Here we use stack top shift + stack bottom shift, which sounds reasonable. +% \begin{macrocode} + \um_stack_num_up:N \scriptstyle + + \um_stack_denom_down:N \scriptstyle + } +% \end{macrocode} +% Here we use the minimum stack gap. +% \begin{macrocode} + \lineskip \um_stack_vgap:N \scriptstyle + \lineskiplimit \lineskip + \ialign + \c_group_begin_token + \token_if_eq_meaning:NNT c #1 { \hfil } + \c_math_shift_token + \m@th + \scriptstyle + \c_parameter_token \c_parameter_token + \c_math_shift_token + \hfil + \crcr + } +% \end{macrocode} +% For \LuaTeX, \cs{frac} and \cs{genfrac} should use \cs{Ustack} for correct math style selection. +% \begin{macrocode} + \um_check_and_fix_luatex:cNnnn { frac~ } \cs_set:Npn { #1 #2 } { + { + \begingroup #1 \endgroup \@@over #2 + } + } { + { + \luatexUstack { \group_begin: #1 \group_end: \@@over #2 } + } + } + \um_check_and_fix_luatex:NNnnn \@genfrac \cs_set_nopar:Npn { + #1 #2 #3 #4 #5 + } { + { + #1 { \begingroup #4 \endgroup #2 #3 \relax #5 } + } + } { + { + #1 { + \luatexUstack { + \group_begin: #4 \group_end: #2 #3 \scan_stop: #5 + } + } + } + } +% \end{macrocode} +% The roots need a complete rework. +% \begin{macrocode} + \um_check_and_fix_luatex:NNnnn \plainroot@ \cs_set_nopar:Npn { #1 \of #2 } { + \setbox \rootbox \hbox { + $ \m@th \scriptscriptstyle { #1 } $ + } + \mathchoice + { \r@@t \displaystyle { #2 } } + { \r@@t \textstyle { #2 } }~ + { \r@@t \scriptstyle { #2 } } + { \r@@t \scriptscriptstyle { #2 } } + \egroup + } { + \bool_if:nTF { + \int_compare_p:nNn { \uproot@ } = { \c_zero } + && \int_compare_p:nNn { \leftroot@ } = { \c_zero } + } { + \luatexUroot \l_um_radical_sqrt_tl { #1 } { #2 } + } { + \hbox_set:Nn \rootbox { + \c_math_shift_token + \m@th + \scriptscriptstyle { #1 } + \c_math_shift_token + } + \mathchoice + { \r@@t \displaystyle { #2 } } + { \r@@t \textstyle { #2 } } + { \r@@t \scriptstyle { #2 } } + { \r@@t \scriptscriptstyle { #2 } } + } + \c_group_end_token + } + \um_check_and_fix:NNnnnn \r@@t \cs_set_nopar:Npn { #1 #2 } { + \setboxz@h { $ \m@th #1 \sqrtsign { #2 } $ } + \dimen@ \ht\z@ + \advance \dimen@ -\dp\z@ + \setbox\@ne \hbox { $ \m@th #1 \mskip \uproot@ mu $ } + \advance \dimen@ by 1.667 \wd\@ne + \mkern -\leftroot@ mu + \mkern 5mu + \raise .6\dimen@ \copy\rootbox + \mkern -10mu + \mkern \leftroot@ mu + \boxz@ + } { + \hbox_set:Nn \l_tmpa_box { + \c_math_shift_token + \m@th + #1 + \mskip \uproot@ mu + \c_math_shift_token + } + \luatexUroot \l_um_radical_sqrt_tl { + \box_move_up:nn { \box_wd:N \l_tmpa_box } { + \hbox:n { + \c_math_shift_token + \m@th + \mkern -\leftroot@ mu + \box_use:N \rootbox + \mkern \leftroot@ mu + \c_math_shift_token + } + } + } { + #2 + } + } { + \hbox_set:Nn \l_tmpa_box { + \c_math_shift_token + \m@th + #1 + \sqrtsign { #2 } + \c_math_shift_token + } + \hbox_set:Nn \l_tmpb_box { + \c_math_shift_token + \m@th + #1 + \mskip \uproot@ mu + \c_math_shift_token + } + \mkern -\leftroot@ mu + \um_mathstyle_scale:Nnn #1 { \kern } { + \fontdimen 63 \l_um_font + } + \box_move_up:nn { + \box_wd:N \l_tmpb_box + + (\box_ht:N \l_tmpa_box - \box_dp:N \l_tmpa_box) + * \number \fontdimen 65 \l_um_font / 100 + } { + \box_use:N \rootbox + } + \um_mathstyle_scale:Nnn #1 { \kern } { + \fontdimen 64 \l_um_font + } + \mkern \leftroot@ mu + \box_use_clear:N \l_tmpa_box + } } % \end{macrocode} +% % \paragraph{\pkg{amsopn}} % This code is to improve the output of analphabetic symbols in text of operator names (\cs{sin}, \cs{cos}, etc.). Just comment out the offending lines for now: % \begin{macrocode} -\um_patch_pkg:nn {amsopn} { +\AtEndOfPackageFile * {amsopn} { \cs_set:Npn \newmcodes@ { \mathcode`\'39\scan_stop: \mathcode`\*42\scan_stop: @@ -5016,9 +5662,40 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % \paragraph{Accents} % \begin{macrocode} -\AtBeginDocument{ +\xetex_or_luatex:nnn { \cs_new_protected_nopar:Npn \um_setup_accents: } { \def\widehat{\hat} \def\widetilde{\tilde} + \def\overrightarrow{\vec} +} { + \cs_gset_protected_nopar:Npx \widehat { + \um_wide_top_accent:Nnn \mathaccent { \um_symfont_tl } { "0302 } + } + \cs_gset_protected_nopar:Npx \widetilde { + \um_wide_top_accent:Nnn \mathaccent { \um_symfont_tl } { "0303 } + } + \cs_gset_protected_nopar:Npx \overleftarrow { + \um_wide_top_accent:Nnn \mathaccent { \um_symfont_tl } { "20D6 } + } + \cs_gset_protected_nopar:Npx \overrightarrow { + \um_wide_top_accent:Nnn \mathaccent { \um_symfont_tl } { "20D7 } + } + \cs_gset_protected_nopar:Npx \overleftrightarrow { + \um_wide_top_accent:Nnn \mathaccent { \um_symfont_tl } { "20E1 } + } + \bool_if:NT \c_um_have_fixed_accents_bool { + \cs_gset_protected_nopar:Npx \underrightharpoondown { + \um_wide_bottom_accent:Nnn \mathaccent { \um_symfont_tl } { "20EC } + } + \cs_gset_protected_nopar:Npx \underleftharpoondown { + \um_wide_bottom_accent:Nnn \mathaccent { \um_symfont_tl } { "20ED } + } + \cs_gset_protected_nopar:Npx \underleftarrow { + \um_wide_bottom_accent:Nnn \mathaccent { \um_symfont_tl } { "20EE } + } + \cs_gset_protected_nopar:Npx \underrightarrow { + \um_wide_bottom_accent:Nnn \mathaccent { \um_symfont_tl } { "20EF } + } + } } % \end{macrocode} % @@ -5029,18 +5706,130 @@ This work is "author-maintained" by Will Robertson. } % \end{macrocode} % -% \paragraph{\pkg{beamer}} -% At end of the package so the warnings are defined. +% \paragraph{\pkg{mathtools}} +% \pkg{mathtools}’s |\cramped| command and others that make use of its internal version use an incorrect font dimension. +% % \begin{macrocode} -\AtEndOfPackage{ - \@ifclassloaded{beamer}{ - \ifbeamer@suppressreplacements\else - \um_warning:n {disable-beamer} - \beamer@suppressreplacementstrue +\AtEndOfPackageFile * { mathtools } { + \um_check_and_fix:NNnnnn \MT_cramped_internal:Nn \cs_set_nopar:Npn { #1 #2 } { + \sbox \z@ { + $ + \m@th + #1 + \nulldelimiterspace = \z@ + \radical \z@ { #2 } + $ + } + \ifx #1 \displaystyle + \dimen@ = \fontdimen 8 \textfont 3 + \advance \dimen@ .25 \fontdimen 5 \textfont 2 + \else + \dimen@ = 1.25 \fontdimen 8 + \ifx #1 \textstyle + \textfont + \else + \ifx #1 \scriptstyle + \scriptfont + \else + \scriptscriptfont + \fi + \fi + 3 \fi - }{} + \advance \dimen@ -\ht\z@ + \ht\z@ = -\dimen@ + \box\z@ + } { +% \end{macrocode} +% \LuaTeX\ has primitives for setting material in cramped mode (thanks to Khaled Hosny for pointing this out). +% Note we don’t use \cs{mathstyle} since we want to patch only a single command. +% \begin{macrocode} + \use:c { luatexcramped \cs_to_str:N #1 } #2 + } { +% \end{macrocode} +% The \XeTeX\ version is pretty similar to the legacy version, only using the correct font dimensions. +% \begin{macrocode} + \hbox_set:Nn \l_tmpa_box { + \color@setgroup + \c_math_shift_token + \m@th + #1 + \dim_zero:N \nulldelimiterspace + \radical \c_zero { #2 } + \c_math_shift_token + \color@endgroup + } + \box_set_ht:Nn \l_tmpa_box { + \box_ht:N \l_tmpa_box +% \end{macrocode} +% Here we use the radical vertical gap. +% \begin{macrocode} + - \um_radical_vgap:N #1 + } + \box_use_clear:N \l_tmpa_box + } +% \end{macrocode} +% +% \begin{macro}{\dblcolon} +% \begin{macro}{\coloneqq} +% \begin{macro}{\Coloneqq} +% \begin{macro}{\eqqcolon} +% \pkg{mathtools} defines several commands as combinations of colons and +% other characters, but with meanings incompatible to \pkg{unicode-math}. +% Thus we issue a warning. Because \pkg{mathtools} uses +% \cmd{\providecommand} \cmd{\AtBeginDocument}, we can just define the +% offending commands here. +% \begin{macrocode} + \msg_warning:nn { unicode-math } { mathtools } + \NewDocumentCommand \dblcolon { } { \Colon } + \NewDocumentCommand \coloneqq { } { \coloneq } + \NewDocumentCommand \Coloneqq { } { \Coloneq } + \NewDocumentCommand \eqqcolon { } { \eqcolon } +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \paragraph{\pkg{colonequals}} +% +% \begin{macro}{\ratio} +% \begin{macro}{\coloncolon} +% \begin{macro}{\minuscolon} +% \begin{macro}{\colonequals} +% \begin{macro}{\equalscolon} +% \begin{macro}{\coloncolonequals} +% Similarly to \pkg{mathtools}, the \pkg{colonequals} defines several colon +% combinations. Fortunately there are no name clashes, so we can just +% overwrite their definitions. +% \begin{macrocode} +\AtEndOfPackageFile * { colonequals } { + \msg_warning:nn { unicode-math } { colonequals } + \RenewDocumentCommand \ratio { } { \mathratio } + \RenewDocumentCommand \coloncolon { } { \Colon } + \RenewDocumentCommand \minuscolon { } { \dashcolon } + \RenewDocumentCommand \colonequals { } { \coloneq } + \RenewDocumentCommand \equalscolon { } { \eqcolon } + \RenewDocumentCommand \coloncolonequals { } { \Coloneq } } % \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \paragraph{\pkg{beamer}} +% \begin{macrocode} +\@ifclassloaded{beamer}{ + \ifbeamer@suppressreplacements\else + \um_warning:n {disable-beamer} + \beamer@suppressreplacementstrue + \fi +}{} +% \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff @@ -5068,10 +5857,6 @@ This work is "author-maintained" by Will Robertson. % \end{macrocode} % % \begin{macrocode} -\msg_new:nnn {unicode-math} {maths-feature-only} -{ - The~ '#1'~ font~ feature~ can~ only~ be~ used~ for~ maths~ fonts. -} \msg_new:nnn {unicode-math} {disable-beamer} { Disabling~ beamer's~ math~ setup.\\ @@ -5102,6 +5887,43 @@ This work is "author-maintained" by Will Robertson. { Setup~ alphabet:~ #1. } +\msg_new:nnn {unicode-math} {macro-expected} +{ + I've~ expected~ that~ #1~ is~ a~ macro,~ but~ it~ isn't. +} +\msg_new:nnn {unicode-math} {wrong-meaning} +{ + I've~ expected~ #1~ to~ have~ the~ meaning~ #3,~ but~ it~ has~ the~ meaning~ #2. +} +\msg_new:nnn {unicode-math} {patch-macro} +{ + I'm~ going~ to~ patch~ macro~ #1. +} +\msg_new:nnn { unicode-math } { mathtools } { + I'm~ going~ to~ overwrite~ the~ following~ commands~ from \\ + the~ `mathtools'~ package: \\ + \token_to_str:N \dblcolon,~ + \token_to_str:N \coloneqq,~ + \token_to_str:N \Coloneqq,~ + \token_to_str:N \eqqcolon. \\ + Note~ that~ since~ I~ won't~ overwrite~ the~ other~ colon-like \\ + commands,~ using~ them~ will~ lead~ to~ inconsistencies. +} +\msg_new:nnn { unicode-math } { colonequals } { + I'm~ going~ to~ overwrite~ the~ following~ commands~ from \\ + the~ `colonequals'~ package: \\ + \token_to_str:N \ratio,~ + \token_to_str:N \coloncolon,~ + \token_to_str:N \minuscolon, \\ + \token_to_str:N \colonequals,~ + \token_to_str:N \equalscolon,~ + \token_to_str:N \coloncolonequals. \\ + Note~ that~ since~ I~ won't~ overwrite~ the~ other~ colon-like \\ + commands,~ using~ them~ will~ lead~ to~ inconsistencies. \\ + Furthermore,~ changing~ \token_to_str:N \colonsep \c_space_tl + or~ \token_to_str:N \doublecolonsep \c_space_tl won't~ have \\ + any~ effect~ on~ the~ re-defined~ commands. +} % \end{macrocode} % % \begin{macrocode} @@ -5206,8 +6028,64 @@ This work is "author-maintained" by Will Robertson. % {\hexnumber@{\count\z@}\hexnumber@{\count\tw@}}} % \end{verbatim} % +% \section{Legacy \TeX\ font dimensions} +% +% \centerline{% +% \begin{tabular}[t]{@{}lp{4cm}@{}} +% \toprule +% \multicolumn{2}{@{}c@{}}{Text fonts} \\ +% \midrule +% $\phi_1$ & slant per pt \\ +% $\phi_2$ & interword space \\ +% $\phi_3$ & interword stretch \\ +% $\phi_4$ & interword shrink \\ +% $\phi_5$ & x-height \\ +% $\phi_6$ & quad width \\ +% $\phi_7$ & extra space \\ +% $\phi_8$ & cap height (\XeTeX\ only) \\ +% \bottomrule +% \end{tabular} +% \quad +% \begin{tabular}[t]{@{}lp{4cm}@{}} +% \toprule +% \multicolumn{2}{@{}c@{}}{Maths font, \cs{fam}2} \\ +% \midrule +% $\sigma_5$ & x height \\ +% $\sigma_6$ & quad \\ +% $\sigma_8$ & num1 \\ +% $\sigma_9$ & num2 \\ +% $\sigma_{10}$ & num3 \\ +% $\sigma_{11}$ & denom1 \\ +% $\sigma_{12}$ & denom2 \\ +% $\sigma_{13}$ & sup1 \\ +% $\sigma_{14}$ & sup2 \\ +% $\sigma_{15}$ & sup3 \\ +% $\sigma_{16}$ & sub1 \\ +% $\sigma_{17}$ & sub2 \\ +% $\sigma_{18}$ & sup drop \\ +% $\sigma_{19}$ & sub drop \\ +% $\sigma_{20}$ & delim1 \\ +% $\sigma_{21}$ & delim2 \\ +% $\sigma_{22}$ & axis height \\ +% \bottomrule +% \end{tabular} +% \quad +% \begin{tabular}[t]{@{}lp{4cm}@{}} +% \toprule +% \multicolumn{2}{@{}c@{}}{Maths font, \cs{fam}3} \\ +% \midrule +% $\xi_8$ & default rule thickness \\ +% $\xi_9$ & big op spacing1 \\ +% $\xi_{10}$ & big op spacing2 \\ +% $\xi_{11}$ & big op spacing3 \\ +% $\xi_{12}$ & big op spacing4 \\ +% $\xi_{13}$ & big op spacing5 \\ +% \bottomrule +% \end{tabular} +% } +% % -% \section{\XeTeX\ math font dimensions} +% \section{\Hologo{XeTeX} math font dimensions} % % These are the extended \cmd\fontdimen s available for suitable fonts % in \XeTeX. Note that Lua\TeX\ takes an alternative route, and this package @@ -5377,7 +6255,11 @@ This work is "author-maintained" by Will Robertson. \usepackage{array,booktabs,calc,enumitem,fancyvrb,graphicx,ifthen,longtable,refstyle,subfig,topcapt,url,varioref,underscore} \setcounter{LTchunksize}{100} \usepackage[slash-delimiter=frac,nabla=literal]{unicode-math} -\usepackage{metalogo} +\usepackage{metalogo,hologo} + +\@ifundefined{HOLOGO@ReflectBox@\hologodriver}{% + \@namedef{HOLOGO@ReflectBox@\hologodriver}{}% +}{} %\usepackage[rm,small]{titlesec} @@ -5388,6 +6270,7 @@ This work is "author-maintained" by Will Robertson. \newfontface\umfont{STIXGeneral} \usepackage{hypdoc} +\hypersetup{linktocpage} \linespread{1.069} % A bit more space between lines \frenchspacing % Remove ugly extra space after punctuation |