% \section{User commands}\label{sec:codeuser}
%
% This section contains the definitions of the commands detailed in
% the user documentation.  Only the `top level' definitions of the
% commands are contained herein; they all use or define macros which
% are defined or used later on in \vref{sec:codeinternal}.
%
% \iffalse
%    \begin{macrocode}
%<*fontspec&(xetexx|luatex)>
%    \end{macrocode}
% \fi
%
% \subsubsection{Font selection}
% \begin{macro}{\fontspec}
%   This is the main command of the package that
%   selects fonts with various features. It takes two arguments: the
%   font name and the optional requested features of that
%   font. Then this new font family is selected.
%    \begin{macrocode}
\NewDocumentCommand \fontspec { O{} m O{} }
  {
    \@@_main_fontspec:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_fontspec:nnn
 {
  \fontspec_set_family:Nnn \f@family {#1,#3} {#2}
  \fontencoding { \l_@@_nfss_enc_tl }
  \selectfont
  \ignorespaces
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setmainfont}
%     The following three macros perform equivalent operations setting
%     the default font for a
%     particular family: `roman', sans serif, or typewriter
%     (monospaced). I end them with |\normalfont| so that if they're
%     used in the document, the change registers immediately.
%    \begin{macrocode}
\DeclareDocumentCommand \setmainfont { O{} m O{} }
  {
    \@@_main_setmainfont:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setmainfont:nnn
 {
  \fontspec_set_family:Nnn \g_@@_rmfamily_family {#1,#3} {#2}
  \tl_set_eq:NN \rmdefault \g_@@_rmfamily_family
  \use:x { \exp_not:n { \DeclareRobustCommand \rmfamily }
   {
    \exp_not:N \fontencoding { \l_@@_nfss_enc_tl }
    \exp_not:N \fontfamily { \g_@@_rmfamily_family }
    \exp_not:N \selectfont
   }
  }
  \str_if_eq_x:nnT {\familydefault} {\rmdefault}
    { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl }
  \normalfont
  \ignorespaces
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setsansfont}
%    \begin{macrocode}
\DeclareDocumentCommand \setsansfont { O{} m O{} }
  {
    \@@_main_setsansfont:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setsansfont:nnn
 {
  \fontspec_set_family:Nnn \g_@@_sffamily_family {#1,#3} {#2}
  \tl_set_eq:NN \sfdefault \g_@@_sffamily_family
  \use:x { \exp_not:n { \DeclareRobustCommand \sffamily }
   {
    \exp_not:N \fontencoding { \l_@@_nfss_enc_tl }
    \exp_not:N \fontfamily { \g_@@_sffamily_family }
    \exp_not:N \selectfont
   }
  }
  \str_if_eq_x:nnT {\familydefault} {\sfdefault}
    { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl }
  \normalfont
  \ignorespaces
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\setmonofont}
%    \begin{macrocode}
\DeclareDocumentCommand \setmonofont { O{} m O{} }
  {
    \@@_main_setmonofont:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setmonofont:nnn
 {
  \fontspec_set_family:Nnn \g_@@_ttfamily_family {#1,#3} {#2}
  \tl_set_eq:NN \ttdefault \g_@@_ttfamily_family
  \use:x { \exp_not:n { \DeclareRobustCommand \ttfamily }
   {
    \exp_not:N \fontencoding { \l_@@_nfss_enc_tl }
    \exp_not:N \fontfamily { \g_@@_ttfamily_family }
    \exp_not:N \selectfont
   }
  }
  \str_if_eq_x:nnT {\familydefault} {\ttdefault}
    { \tl_set_eq:NN \encodingdefault \l_@@_nfss_enc_tl }
  \normalfont
  \ignorespaces
 }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\setromanfont}
% This is the old name for \cs{setmainfont}, retained \emph{ad infinitum}
% for backwards compatibility. It was deprecated in 2010.
%    \begin{macrocode}
\DeclareDocumentCommand \setromanfont { O{} m O{} }
  {
    \@@_main_setmainfont:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\setmathrm}
% \begin{macro}{\setmathsf}
% \begin{macro}{\setboldmathrm}
% \begin{macro}{\setmathtt}
% These commands are analogous to \cmd\setmainfont\ and others,
% but for selecting the font used for \cmd\mathrm, \etc. They
% can only be used in the preamble of the
% document. \cmd\setboldmathrm\ is used for specifying which
% fonts should be used in \cmd\boldmath.
%    \begin{macrocode}
\DeclareDocumentCommand \setmathrm { O{} m O{} }
  {
    \@@_main_setmathrm:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setmathrm:nnn
 {
  \fontspec_set_family:Nnn \g_@@_mathrm_tl {#1} {#2}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareDocumentCommand \setboldmathrm { O{} m O{} }
  {
    \@@_main_setboldmathrm:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setboldmathrm:nnn
 {
  \fontspec_set_family:Nnn \g_@@_bfmathrm_tl {#1} {#2}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareDocumentCommand \setmathsf { O{} m O{} }
  {
    \@@_main_setmathsf:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setmathsf:nnn
 {
  \fontspec_set_family:Nnn \g_@@_mathsf_tl {#1} {#2}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\DeclareDocumentCommand \setmathtt { O{} m O{} }
  {
    \@@_main_setmathtt:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_setmathtt:nnn
 {
  \fontspec_set_family:Nnn \g_@@_mathtt_tl {#1} {#2}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\@onlypreamble\setmathrm
\@onlypreamble\setboldmathrm
\@onlypreamble\setmathsf
\@onlypreamble\setmathtt
%    \end{macrocode}
% If the commands above are not executed, then \cmd\rmdefault\ (\etc)
% will be used.
%    \begin{macrocode}
\tl_set:Nn \g_@@_mathrm_tl {\rmdefault}
\tl_set:Nn \g_@@_mathsf_tl {\sfdefault}
\tl_set:Nn \g_@@_mathtt_tl {\ttdefault}
%    \end{macrocode}
% \end{macro} \end{macro} \end{macro}
% \end{macro}
%
% \begin{macro}{\newfontfamily}
%   This macro takes the arguments of \cs{fontspec} with a prepended
%   \meta{instance cmd}. This command is used
%   when a specific font instance needs to be referred to repetitively
%   (\eg, in a section heading) since continuously calling
%   \cs{fontspec_select:nn} is inefficient because it must parse the
%   option arguments every time.
%
%   \cs{fontspec_select:nn} defines a font family and saves its name in
%   \cs{l_fontspec_family_tl}. This family is then used in a typical NFSS \cmd\fontfamily\
%   declaration, saved in the macro name specified.
%    \begin{macrocode}
\DeclareDocumentCommand \newfontfamily { m O{} m O{} }
  {
    \@@_main_newfontfamily:nnnn {#1} {#2} {#3} {#4}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_newfontfamily:nnnn
 {
  \fontspec_set_family:cnn { g_@@_ \cs_to_str:N #1 _family } {#2,#4} {#3}
  \use:x
   {
    \exp_not:N \DeclareRobustCommand \exp_not:N #1
     {
      \exp_not:N \fontfamily { \use:c {g_@@_ \cs_to_str:N #1 _family} }
      \exp_not:N \fontencoding { \l_@@_nfss_enc_tl }
      \exp_not:N \selectfont
     }
   }
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newfontface}
% \cmd\newfontface\ uses the fact that if the argument to \feat{BoldFont}, etc., is empty (\ie, |BoldFont={}|), then no bold font is searched for.
%    \begin{macrocode}
\DeclareDocumentCommand \newfontface { m O{} m O{} }
  {
    \@@_main_newfontface:nnnn {#1} {#2} {#3} {#4}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_newfontface:nnnn
 {
  \newfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3}
 }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Font feature selection}
%
% \begin{macro}{\defaultfontfeatures}
%   This macro takes one argument that consists of all of feature
%   options that will be applied by default to all subsequent
%   \cs{fontspec}, et al., commands. It stores its value in
%   \cs{g_fontspec_default_fontopts_tl} (initialised empty), which is
%   concatenated with the individual macro choices in the
%   [...] macro.
%
%    \begin{macrocode}
\DeclareDocumentCommand \defaultfontfeatures { t+ o m }
  {
    \IfNoValueTF {#2}
     { \@@_set_default_features:nn {#1} {#3} }
     { \@@_set_font_default_features:nnn {#1} {#2} {#3} }
    \ignorespaces
  }
\cs_new:Nn \@@_set_default_features:nn
  {
    \IfBooleanTF {#1} \clist_put_right:Nn \clist_set:Nn
      \g_@@_default_fontopts_clist {#2}
  }
%    \end{macrocode}
% The optional argument specifies a font identifier.
% Branch for either (a)~single token input such as \verb|\rmdefault|, or (b)~otherwise assume its a fontname.
% In that case, strip spaces and file extensions and lower-case to ensure consistency.
%    \begin{macrocode}
\cs_new:Nn \@@_set_font_default_features:nnn
 {
  \clist_map_inline:nn {#2}
   {
    \tl_if_single:nTF {##1}
     { \tl_set:No \l_@@_tmp_tl { \cs:w g_@@_ \cs_to_str:N ##1 _family\cs_end: } }
     { \@@_sanitise_fontname:Nn \l_@@_tmp_tl {##1} }

    \IfBooleanTF {#1}
     {
      \prop_get:NVNF \g_@@_fontopts_prop \l_@@_tmp_tl \l_@@_tmpb_tl
       { \tl_clear:N \l_@@_tmpb_tl }
      \tl_put_right:Nn \l_@@_tmpb_tl {#3,}
      \prop_gput:NVV   \g_@@_fontopts_prop \l_@@_tmp_tl \l_@@_tmpb_tl
     }
     {
      \tl_if_empty:nTF {#3}
       { \prop_gremove:NV \g_@@_fontopts_prop \l_@@_tmp_tl }
       { \prop_put:NVn    \g_@@_fontopts_prop \l_@@_tmp_tl {#3,} }
     }
   }
 }
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\addfontfeatures}
%   In order to be able to extend the feature selection of
%   a given font, two things need to be known: the currently selected
%   features, and the currently selected font. Every time a font
%   family is created, this information is saved inside a control
%   sequence with the name of the font family itself.
%
%   This macro extracts this information, then appends the requested
%   font features to add to the already existing ones, and calls the
%   font again with the top level \cs{fontspec} command.
%
%   The default options are \emph{not} applied (which is why
%   \cs{g_fontspec_default_fontopts_tl} is emptied inside the group; this is allowed
%   as \cmd\l_fontspec_family_tl\ is globally defined in \cmd\@@_select_font_family:nn), so this
%   means that the only added features to the font are strictly those
%   specified by this command.
%
%   \cs{addfontfeature} is defined as an alias, as I found that I
%   often typed this instead when adding only a single font feature.
%    \begin{macrocode}
\DeclareDocumentCommand \addfontfeatures {m}
  {
    \@@_main_addfontfeatures:n {#1}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_addfontfeatures:n
 {
%<debug>  \typeout{^^J::::::::::::::::::::::::::::::::::^^J: addfontfeatures}
  \fontspec_if_fontspec_font:TF
   {
    \group_begin:
      \keys_set_known:nnN {fontspec-addfeatures} {#1} \l_@@_tmp_tl
      \prop_get:cnN {g_@@_ \f@family _prop} {options} \l_@@_options_tl
      \prop_get:cnN {g_@@_ \f@family _prop} {fontname} \l_@@_fontname_tl
      \bool_set_true:N \l_@@_disable_defaults_bool
%<debug>          \typeout{ \@@_select_font_family:nn { \l_@@_options_tl , #1 } {\l_@@_fontname_tl} }
      \use:x
       {
        \@@_select_font_family:nn
          { \l_@@_options_tl , #1 } {\l_@@_fontname_tl}
       }
    \group_end:
    \fontfamily\l_fontspec_family_tl\selectfont
   }
   {
    \@@_warning:nx {addfontfeatures-ignored} {#1}
   }
  \ignorespaces
 }
\cs_set_eq:NN \addfontfeature \addfontfeatures
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Defining new font features}
%
% \begin{macro}{\newfontfeature}
%   \cs{newfontfeature} takes two arguments: the name of the feature
%   tag by which to reference it, and the string that is used to
%   select the font feature.
%    \begin{macrocode}
\DeclareDocumentCommand \newfontfeature {mm}
  {
    \@@_main_newfontfeature:nn {#1} {#2}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_newfontfeature:nn
 {
  \keys_define:nn { fontspec }
   {
    #1 .code:n =
     {
      \@@_update_featstr:n {#2}
     }
   }
 }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\newAATfeature}
% This command assigns a new AAT feature by its code (|#2|,|#3|) to a new name (|#1|).
% Better than \cmd\newfontfeature\ because it checks if the feature exists in the
% font it's being used for.
%    \begin{macrocode}
\DeclareDocumentCommand \newAATfeature {mmmm}
  {
    \@@_main_newAATfeature:nnnn {#1} {#2} {#3} {#4}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_newAATfeature:nnnn
 {
  \keys_if_exist:nnF { fontspec } {#1}
    { \@@_define_aat_feature_group:n {#1} }

  \keys_if_choice_exist:nnnT {fontspec} {#1} {#2}
    { \@@_warning:nxx {feature-option-overwrite} {#1} {#2} }

  \@@_define_aat_feature:nnnn {#1}{#2}{#3}{#4}
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newopentypefeature}
% This command assigns a new OpenType feature by its abbreviation (|#2|) to a new name (|#1|).
% Better than \cmd\newfontfeature\ because it checks if the feature exists in the
% font it's being used for.
%    \begin{macrocode}
\DeclareDocumentCommand \newopentypefeature {mmm}
  {
    \@@_main_newopentypefeature:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_newopentypefeature:nnn
 {
  \keys_if_exist:nnF { fontspec / options } {#1}
    { \@@_define_opentype_feature_group:n {#1} }

  \keys_if_choice_exist:nnnT {fontspec} {#1} {#2}
    { \@@_warning:nxx {feature-option-overwrite} {#1} {#2} }

  \exp_args:Nnnx \@@_define_opentype_feature:nnnnn
    {#1} {#2} { \@@_strip_plus_minus:n {#3} } {#3} {}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \@@_strip_plus_minus:n { \@@_strip_plus_minus_aux:Nq #1 \q_nil }
\cs_new:Npn \@@_strip_plus_minus_aux:Nq #1#2 \q_nil
  {
    \str_case:nnF {#1} { {+} {#2} {-} {#2} } {#1#2}
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newICUfeature}
% Deprecated.
%    \begin{macrocode}
\DeclareDocumentCommand \newICUfeature {mmm}
  {
    \@@_main_newopentypefeature:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\aliasfontfeature}
% User commands for renaming font features and font feature options.
%    \begin{macrocode}
\DeclareDocumentCommand \aliasfontfeature {mm}
  {
    \@@_main_aliasfontfeature:nn {#1} {#2}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_aliasfontfeature:nn
 {
%<debug> \typeout{::::::::::::::::::::^^J:: aliasfontfeature{#1}{#2}}
  \bool_set_false:N \l_@@_alias_bool

  \clist_map_inline:Nn \g_@@_all_keyval_modules_clist
   {
     \keys_if_exist:nnT {##1} {#1}
      {
%<debug> \typeout{:::: Key~exists~##1~/~#1}
        \bool_set_true:N \l_@@_alias_bool
        \keys_define:nn {##1}
          { #2 .code:n = { \keys_set:nn {##1} { #1 = {####1} } } }
      }
   }

  \bool_if:NF \l_@@_alias_bool
    { \@@_warning:nx {rename-feature-not-exist} {#1} }
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\aliasfontfeatureoption}
%    \begin{macrocode}
\DeclareDocumentCommand \aliasfontfeatureoption {mmm}
  {
    \@@_main_aliasfontfeatureoption:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_aliasfontfeatureoption:nnn
 {
  \bool_set_false:N \l_@@_alias_bool

  \clist_map_inline:Nn \g_@@_all_keyval_modules_clist
   {
     \keys_if_exist:nnT { ##1 / #1 } {#2}
      {
%<debug> \typeout{:::: Keyval~exists~##1~/~#1~=~#2}
        \bool_set_true:N \l_@@_alias_bool
        \keys_define:nn { ##1 / #1 }
          { #3 .code:n = { \keys_set:nn {##1} { #1 = {#2} } } }
      }

     \keys_if_exist:nnT { ##1 / #1 } {#2Reset}
      {
%<debug> \typeout{:::: Keyval~exists~##1~/~#1~=~#2Reset}
        \keys_define:nn { ##1 / #1 }
          { #3Reset .code:n = { \keys_set:nn {##1} { #1 = {#2Reset} } } }
      }

     \keys_if_exist:nnT { ##1 / #1 } {#2Off}
      {
%<debug> \typeout{:::: Keyval~exists~##1~/~#1~=~#2Off}
        \keys_define:nn { ##1 / #1 }
          { #3Off .code:n = { \keys_set:nn {##1} { #1 = {#2Off} } } }
      }
   }

  \bool_if:NF \l_@@_alias_bool
    { \@@_warning:nx {rename-feature-not-exist} {#1/#2} }
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newfontscript}
% Mostly used internally, but also possibly useful for users, to define new OpenType
% `scripts', mapping logical names to OpenType script tags.
%    \begin{macrocode}
\DeclareDocumentCommand \newfontscript {mm}
 {
  \fontspec_new_script:nn {#1} {#2}
 }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\newfontlanguage}
% Mostly used internally, but also possibly useful for users, to define new OpenType
% `languages', mapping logical names to OpenType language tags.
%    \begin{macrocode}
\DeclareDocumentCommand \newfontlanguage {mm}
 {
  \fontspec_new_lang:nn {#1} {#2}
 }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\DeclareFontsExtensions}
% \texttt{dfont} would never be uppercase, right?
%    \begin{macrocode}
\DeclareDocumentCommand \DeclareFontsExtensions {m}
  {
    \@@_main_DeclareFontsExtensions:n {#1}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_DeclareFontsExtensions:n
 {
  \clist_set:Nn \l_@@_extensions_clist { #1 }
  \tl_remove_all:Nn \l_@@_extensions_clist {~}
 }
\DeclareFontsExtensions{.otf,.ttf,.OTF,.TTF,.ttc,.TTC,.dfont}
%    \end{macrocode}
% \end{macro}


% \begin{macro}{\IfFontFeatureActiveTF}
%    \begin{macrocode}
\DeclareDocumentCommand \IfFontFeatureActiveTF {mmm}
  {
    \@@_main_IfFontFeatureActiveTF:nnn {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_set:Nn \@@_main_IfFontFeatureActiveTF:nnn
  {
%<debug>    \typeout{^^J:::::::::::::::::::::::::::::::::::::::::::::::}
%<debug>    \typeout{:IfFontFeatureActiveTF \exp_not:n{{#1}{#2}{#3}}}
    \@@_if_font_feature:nTF {#1} {#2} {#3}
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \@@_if_font_feature:n {TF}
  {
    \tl_gclear:N \g_@@_single_feat_tl
    \group_begin:
      \@@_font_suppress_not_found_error:
      \@@_init:
      \bool_set_true:N \l_@@_ot_bool
      \bool_set_true:N \l_@@_never_check_bool
      \bool_set_false:N \l_@@_firsttime_bool
      \clist_clear:N \l_@@_fontfeat_clist
      \@@_get_features:Nn \l_@@_rawfeatures_sclist {#1}
    \group_end:

%<debug>    \typeout{:::> \exp_not:N\l_@@_rawfeatures_sclist->~{\l_@@_rawfeatures_sclist}}
%<debug>    \typeout{:::> \exp_not:N\g_@@_single_feat_tl->~{\g_@@_single_feat_tl}}

    \tl_if_empty:NTF \g_@@_single_feat_tl { \prg_return_false: }
      {
        \exp_args:NV \fontspec_if_current_feature:nTF \g_@@_single_feat_tl
          { \prg_return_true: } { \prg_return_false: }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \iffalse
%    \begin{macrocode}
%</fontspec&(xetexx|luatex)>
%    \end{macrocode}
% \fi
