%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \loadmath {Unicode Math fonts <2023-01-17>} % preloaded in format

   \_doc -----------------------------
   \`\loadmath` `{<Unicode-math font>}` loads the given font. It does:
   \begitems
   * define \`\_unimathfont` as `<Unicode-math font>`,
   * redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts,
   * load the `\_unimathfont` by `\normalmath`,
   * print information about the loaded font on the terminal,
   * redefine all encoding dependent setting by `\input unimath-codes.opm`,
   * protect new loading by setting \`\_ifmathloading` to false.
   \enditems
   \`\noloadmath` disallows Unicode-math loading by \`\_mathloadingfalse`.\nl
   \`\doloadmath` allows Unicode-math loading by \`\_mathloadingtrue`.
   \_cod -----------------------------

\_newifi \_ifmathloading   \_mathloadingtrue

\_def\_noloadmath{\_mathloadingfalse}
\_def\_doloadmath{\_mathloadingtrue}

\_def\_loadmath#1{%
   \_ifmathloading
   \_initunifonts
   \_isfont{#1}\_iffalse
      \_opwarning{Math font "#1" not found, skipped...}%
   \_else
      \_def\_unimathfont{#1}%
      \_let\_normalmath = \_normalunimath  \_let\_boldmath = \_boldunimath
      \_normalmath
      \_wterm {MATH-FONT: "#1" -- unicode math prepared.}%
      \_ifx\_ncharrmA\_undefined \_opinput {unimath-codes.opm}\_fi
      \_mathloadingfalse
   \_fi\_fi}

\_public \loadmath \noloadmath \doloadmath ;

   \_doc -----------------------------
   \`\loadboldmath` `{<bold-font>} \to {<normal-font>}`
   defines \`\_unimathboldfont` as `<bold-font>` only if `\_unimathfont` is
   defined as `<normal-font>`. It is used when \^`\boldmath` macro is run.
   When no `\_unimathboldfont` is defined then the `\boldmath` macro
   use \"fake bold" generated by `embolden` \LuaTeX/ font feature.
   \_cod -----------------------------

\_def\_loadboldmath#1#2\to #3{%
   \_def\_tmp{#3}\_ifx\_unimathfont\_tmp % do work only if #3 is loaded as normal Math
   \_isfont{#1}\_iffalse
      \_opwarning{Bold-Math font "#1" not found, skipped...}
   \_else
      \_def\_unimathboldfont{#1}%
      \_wterm {MATH-FONT: "#1" -- unicode math bold prepared.}%
   \_fi\_fi}

\_public \loadboldmath ;

   \_doc -----------------------------
   The Unicode version of the \^`\normalmath` and \^`\boldmath` macros
   are defined here as \`\_normalunimath` and \`\_boldunimath` macros.
   They are using \`\_setunimathdimens` in a similar sense as
   \^`\_setmathdimens`.
   \nl
   You can combine more fonts if you register them to another
   math families (5, 6, 7, etc.) in the \^`\normalmath` macro.
   \nl
   The default value of \^`\_normalunimath` shows a combination of base Unicode-math
   font at family 1 with 8bit Math font at family 4. See definition of `\script` macro where
   `\fam4` is used.
   \_cod -----------------------------

\_def\_normalunimath{%
    \_setmathfamily 0 \_tenrm             % font for non-math objects in math mode
    \_loadumathfamily 1 {\_unimathfont}{} % Base font
    \_loadmathfamily  4 rsfs              % script
    \_setunimathdimens
}%
\_def\_boldunimath{%
    \_setmathfamily 0 \_tenbf             % font for non-math objects in math mode
    \_ifx\_unimathboldfont \_undefined
       \_loadumathfamily 1 {\_unimathfont}{embolden=1.7;} % Base faked bold
    \_else
       \_loadumathfamily 1 {\_unimathboldfont}{} % Base real bold font
    \_fi
    \_loadmathfamily  4 rsfs              % script
    \_setunimathdimens
}%
\_def\_setunimathdimens{% PlainTeX sets these dimens for 10pt size only:
  \_delimitershortfall=0.5\_fontdimen6\_textfont1
  \_nulldelimiterspace=0.12\_fontdimen6\_textfont1
  \_setmathparam\_Umathspaceafterscript \_scriptspacefactor
  \_setbox0=\_hbox{\_everymath{}$\_fam1\_displaystyle{0\_atop0}$}%
  \_Umathfractiondelsize\_displaystyle = \_dimexpr(\_ht0-\_Umathaxis\_displaystyle)*2\_relax
  \_setbox0=\_box\_voidbox
}

   \_doc -----------------------------
   If you try the example above about
   \~`\loadboldmath``{[xitsmath-bold]} \to {[xitsmath-regular]}`
   then you can find a bug in XITSMath-Bold font: the symbols for norm
   $\|x\|$ are missing. So, we have to define `\_boldmath` macro manually.
   The missing symbol is loaded from family 5 as no-bold variant in our example:
   \begtt
   \loadmath{[xitsmath-regular]}
   \def\_boldmath{%
      \_loadumathfamily 1 {[xitsmath-bold]}{} % Base font
      \_loadmathfamily 4  rsfs % script
      \_loadumathfamily 5 {[xitsmath-regular]}{}
      \_def\|{\_Udelimiter 0 5 "02016 }%      % norm delimiter from family 5
      \_setmathdimens
   }
   \endtt

   \`\_loadumathfamily` `<number> {<font>}{<font features>}`
   loads the given Unicode-math fonts in three sizes
   using single <font> with different `mathsize=1,2,3` font features.
   The math font family is set with given `<number>`.
   The `<font features>` are added to the default
   \`\_mfontfeatures` and to the size-dependent features `ssty=1`
   if script size is asked or `ssty=2` if scriptscriptsize is asked.\nl
   \`\_mparams` can insert additional font features
   dependig on the current `\_mfam`.\nl
   The \^`\_mfactor` `<family><space>` sets scaling factor,
   see section~\ref[math-preload] for more information.\nl
   The \`\_textmff`, \`\_scriptmff` and \`\_sscriptmff` are font
   features for text, script and sscript sizes respectively. They are
   locally re-defined in \^`\mathbox` macro.
   \_cod -----------------------------

\_def\_umathname#1#2{"#1:\_mfontfeatures#2"}
\_def\_mfontfeatures{mode=base;script=math;}

\_def\_loadumathfamily{\_afterassignment\_loadumathfamilyA \_chardef\_mfam}
\_def\_loadumathfamilyA #1#2 {\_mfactor
  \_font\_mF \_umathname{#1}{\_textmff   \_mparams #2} at\_sizemtext \_textfont        \_mfam=\_mF
  \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont      \_mfam=\_mF
  \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont\_mfam=\_mF
}
\_def\_textmff   {ssty=0;mathsize=1;}
\_def\_scriptmff {ssty=1;mathsize=2;}
\_def\_sscriptmff{ssty=2;mathsize=3;}
\_def\_mparams{}

   \_doc -----------------------------
   \`\addUmathfont` `<fam> {[<normal-font>]}{<ffeatures>} {[<bold-font>]}{<ffeatures>} {<factor>}`
   allocates new <fam> using \^`\newfam` and adds loading this font to the
   \~`\normalmath` and \~`\boldmath` macros. Note that allocationos using
   \^`\newfam` starts from 43 because numbers 1--42 are reserved for direct
   usage without \^`\newfam`.
   We use \^`\aheadto` here because we want to read the main family 1 as
   last one (for definitive setting of math parameters).
   \_cod -----------------------------

\_def\_addUmathfont #1#2#3#4#5#6{% #1: fam (will be set), #2#3: normal font, #4#5: bold font
   \_ifx\_ncharrmA\_undefined \_errmessage{basic Unicode math font must be loaded first}%
   \_else \_isfont{#2}\_iffalse \_opwarning{font #2 is unavailable}%
   \_else
      \_newfam#1\_relax
      \_sdef{_mfactor:\_the\_numexpr#1\_relax}{#6}%
      \_global\_aheadto\_normalmath{\_loadumathfamily #1{#2}{#3} }%
      \_ifx\_relax#4\_relax
         \_global\_aheadto\_boldmath{\_loadumathfamily #1{#2}{embolden=1.7;} }%
      \_else
         \_global\_aheadto\_boldmath{\_loadumathfamily #1{#4}{#5} }%
      \_fi
      \_normalmath
      \_wterm{add-MATH-FONT: #1=\the#1, "#2", \ifx"#4"\else bold: "#4"\fi}%
   \_fi \_fi
}

   \_doc -----------------------------
   The math characters can be given directly (by their Unicode) or by a macro
   like `\doteq`, `\times`, etc. These macros simply expand to the math character
   with its Unicode. And this math character has its `\Umathcode` given by
   <class>, <family>, <slot-number>. Sometimes, we may want to get these
   quantities from the given Unicode math character by our macros. It is
   possible by \`\themathcodeclass``<math-char>`,
   \`\themathcodefam``<math-char>` and \`\themathcodechar``<math-char>` macros.
   The parameter <math-char> is a math character or it is a macro like `\doteq`, `\times`.
   Moreower, \`\thedelcodefam``<math-char>` and \`\thedelcodechar``<math-char>`
   return delcode quaitities of givem math character.
   \_cod -----------------------------

\_def\_getmathcode#1#2{\_directlua{tex.print(tex.get#2code(token.scan_int())[#1])}}
\_def\_themathcodeclass #1{\_getmathcode 1{math}\_ea`#1 }
\_def\_themathcodefam   #1{\_getmathcode 2{math}\_ea`#1 }
\_def\_themathcodechar  #1{\_getmathcode 3{math}\_ea`#1 }
\_def\_thedelcodefam    #1{\_getmathcode 1{del}\_ea`#1 }
\_def\_thedelcodechar   #1{\_getmathcode 2{del}\_ea`#1 }

\_public \themathcodeclass \themathcodefam \themathcodechar \thedelcodefam \thedelcodechar ;

   \_doc -----------------------------
   \`\mathchars` `<fam> {<list of sequences>}`
   saves <fam> to \`\_mafam` and runs for each sequence from the <list of sequences>
   the relevant code settings using `\Umathcode` primitive.
   In case of `\int`-like operators the <math class>=8 and we only
   re-declare `\_int:<int-character>` as an operator with the new \^`\_mafam`.
   Note that the used primitives have the syntax:
   \begtt \catcode`<=13
   \Umathchardef <sequence> = <math class> <math family> <slot number>
   \Umathcode <code>        = <math class> <math family> <slot number>
   \Udelcode <code>         = <math family> <slot number>
   \endtt
   \_cod -----------------------------

\_def\_mathchars {\_afterassignment\_mathcharsA \_chardef\_mafam=}
\_def\_mathcharsA #1{\_foreach #1\_do{%
   \_chardef\_tmp=\_themathcodeclass##1\_relax
   \_ifnum\_tmp=8 % \int, \iint, \oint, etc.
       \_ea\_Umathchardef \_csname _int:##1\_endcsname =1 \_mafam \_ea`##1
   \_else
       \_Umathcode \_ea`##1=\_tmp \_mafam \_themathcodechar##1
   \_fi
}}

   \_doc -----------------------------
   \`\mathcodes` `<fam> {<list of pairs>}` sets mathcodes of given
   characters with explicit <class>es. Each pair can be `<class>{<list of chars>}`
   and `<list of chars>` can include \`\Urange` `<from>-<to>`.
   This is reason why we apply `\expanded` to the `<list of chars>`
   before reading it by \^`\foreach`: the \^`\Urange` is expandable
   and expands to the relevant list of characters.
   \_cod -----------------------------

\_def\_mathcodes{\_afterassignment\_mathcodesA\_chardef\_mafam=}
\_def\_mathcodesA#1{%
   \_foreach #1\_do ##1##2{%
      \_ea\_foreach\_expanded{##2}\_do{\_Umathcode `####1=##1\_mafam \_ea`####1}%
   }%
}
\_def\_Urange #1-#2{\_fornum \_ea`#1..\_ea`#2\_do{\_Uchar##1 }}

\_public \addUmathfont \mathchars \mathcodes \Urange ;

\_endcode


The \^`\loadmath` `{<Unicode-math font>}` macro loads math fonts and
redefines all default math-codes using `\input unimath-codes.opm`.
If Unicode-math font is loaded then \^`\_mathloadingfalse`
is set, so the new Unicode-math font isn't loaded until \^`\doloadmath` is used.

\^`\loadboldmath` `{<bold-font>} \to {<normal-font>}` loads bold variant only
if `<normal-font>` was sucessully loaded by the previous `\loadmath`. For example:

\begtt
\loadmath     {[xitsmath-regular]}
\loadboldmath {[xitsmath-bold]} \to {[xitsmath-regular]}
\endtt
There are very few Unicode-math fonts with full \~`\boldmath` support.
I know only XITSMath-Bold and KpMath-Bold. If \^`\loadboldmath` is not used
then \"faked bold" created from \~`\normalmath` is used by default.

The {\em main math font} is loaded by \^`\loadmath` (typically indirectly using
\^`\fontfam`) and you can load more {\em additional math fonts} by
\^`\addUmathfont`:
\begtt \catcode`<=13
\addUmathfont \famname {[<normal-font>]}{<ffeatures>} {[<bold-font>]}{<ffeatures>} {<factor>}
\endtt
The `\famname` is a control sequence declared by \^`\addUmathfont` for later
use. It gets math family number. The `<factor>` is decimal number for size
corrections in view of the main math font. If it is empty then <factor>=1.
If <bold-font> is empty, the \"faked bold" derived from <normal-font> is used.
Example:
\begtt
\fontfam[lm]  % does \lodmath{[latinmodern-math]}
\addUmathfont \xits {[XITSMath-Regular]}{} {[XITSMath-Bold]}{} {}
\endtt
%
declares `latinmodern-math` as main math font (its bold variant is \"faked bold").
The additional math font family `\xits` is declared in the example. It uses
`XITSMath-Regular` for normal printing and `XITSMath-Bold` for bold printing.

All characters used in math formula are printed from main math font by
default. But you can re-declare characters for printing from
additional font by \^`\mathchars` `\famname {<list of sequences>}`. For
example:

\begtt
\mathchars \xits {\stareq \triangleq \veeeq \wedgeq}
\endtt
%
sets the characters `\stareq`, `\triangleq`, `\veeeq`, `\wedgeq` from
the `\xits` additional font. The <list of sequences> can include
control sequences from the `unicode-table.tex`, but no math
accents. These contol sequences can be printed by `\input print-unimath.opm`.

The \^`\mathchars` macro keeps the class and slot of declared math objects
and re-declares only family of them. It is applied to all control
sequences given in the parameter. The relevant math codes are re-declared.

Use `\addto\selector{\fam\famname}` if you want to print whole math alphabet
from an additional math font. For example `\addto\cal{\fam\xits}`
declares all `\cal` characters from the `\xits` font loaded by
\^`\addUmathfont`.

The \^`\mathcodes` macro provides comfortable settings of math codes of math
objects. Its syntax is \^`\mathcodes` `<family> {<list-of-pairs>}`. Each pair
in the <list-of-pairs> is `<class-number><character>` (separated by optional
space) or `<class-number>{<list-of-characters>}`. The <list-of-characters>
includes declared characters or \^`\Urange` `<from>-<to>` which is equal to the
list of characters beginning <from> and ending <to>, for example
`\Urange a-d` is equal to `abcd`. The characters can be given directly or
by the math sequences like `\times`, `\doteq` too.

The \^`\mathcodes` macro declares mathcode of given characters internally by
\begtt \catcode`<=13
\Umathcode `<character> = <class-number> <family> `<character>
\endtt

The \^`\mathcodes` macro sets math codes of given Unicode characters.
The relevant control sequence from `unicode-table.tex` changes its
behavior too. For example, If you change math code of × then the
`\times` control sequence will behave like new declared ×.


\secc Unicode-math macros preloaded in the format

\printdoc unimath-macros.opm


\secc[unimath-codes] Macros and codes set when `\loadmath` is processed firstly

The file `unimath-codes.opm` is loaded when the \^`\loadmath` is used. The
macros here redefines globally all encoding dependent settings declared in
the section~\ref[math-macros].

\printdoc     unimath-codes.opm
\printdoctail unimath-codes.opm

\secc Printing all Unicode math slots in used math font

\printdoctail print-unimath.opm
\printdoc     print-unimath.opm

\_endinput

2023-01-17 \mathchars: \int operators re-implemented
2023-01-15 \_def\_umathrange moved to unimath-codes.opm
2023.01-15 \themathcodeclass etc. introduced
2022-12-01 reading number by \_loadumathfamily more robust
2022-11-18 \mathchars improved, \Udelcodes are set too, \addUmathfont uses \ahead
2022-11-17 \Umathchardef replaced by \chardef
2022-11-16 \resetmathchars removed, \mathchars, \mathcodes introduced
2022-11-13 \_setfontfamily 0 added.
2022-07-22 \Umathspaceafterscript setting added.
2022-06-10 \addUmathfont and \resetmathchars added.
2021-08-16 \_loadumathfamily simplified, used mathsize= font feature.
2021-08-16 nomathparam font feature used for families > 3 (bug fixed).
2021-08-02 ssty fontfeatures rewritten; fam2, fam3 unused, \scriptspace not set
2021-04-04 \_setunimathdimens: \setbox0=\box\voidbox added
2021-03-09 \_setunimathdimes: \_begin/end/group instead {}, bug fixed
2021-02-15 \_textmff, \_scriptmff and \_sscriptmff introduced
2021-02-15 \_expandafter -> \_ea
2020-06-07 \Umathfractiondelsize (for \choose brackets) corrected, see https://tug.org/pipermail/luatex/2020-June/007365.html
2020-04-15 \_setmathdimens -> \_setuniathdimens
2020-02-25 implemented
