% \iffalse meta-comment
%
%% File: tagpdf-space.dtx
%
% Copyright (C) 2019-2026 Ulrike Fischer
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
% This file is part of the "tagpdf bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/latex3/tagpdf
%
% for those people who are interested.
%<*driver>
\DocumentMetadata{tagging=on}
\documentclass{l3in2edoc}
\usepackage{array,booktabs,caption}
\hypersetup{pdfauthor=Ulrike Fischer,
 pdftitle=tagpdf-space module (tagpdf)}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% \title{^^A
%   The \pkg{tagpdf-space} module\\ Code related to real space chars   ^^A
% }
%
% \author{^^A
%  Ulrike Fischer\thanks
%    {^^A
%      E-mail:
%        \href{mailto:fischer@troubleshooting-tex.de}
%          {fischer@troubleshooting-tex.de}^^A
%    }^^A
% }
%
% \date{Version 1.0b, released 2026-04-24}
% \maketitle
% \begin{documentation}
% \begin{function}{activate/space (setup-key),interwordspace (deprecated)}
% This key allows to activate/deactivate the real space chars if the engine supports
% it. The allowed values are |true|, |on|, |false|, |off|.
% The old name of the key |interwordspace| is still supported but deprecated.
% \end{function}
% \begin{function}{show-spaces (deprecated)}
% This key is deprecated. Use |debug/show=spaces| instead. 
% This key works only with luatex and shows with small red
% bars where spaces have been inserted. This is only for debugging and
% is not completely reliable (and change affect other literals and tagging), so it
% should be used with care.
% \end{function}
% \end{documentation}
% \begin{implementation}
%    \begin{macrocode}
%<@@=tag>
%<*header>
\ProvidesExplPackage {tagpdf-space-code} {2026-04-24} {1.0b}
 {part of tagpdf - code related to real space chars}
%</header>
%    \end{macrocode}
% \section{Code for interword spaces}
% The code is engine/backend dependent. Basically only pdftex and luatex
% support real space chars. Most of the code for luatex which uses attributes
% is in the lua code, here are only the keys.
%
% \begin{macro}{activate/spaces (setup-key),interwordspace (deprecated),show-spaces (deprecated)}
%    \begin{macrocode}
%<*package>
\bool_new:N\l_@@_showspaces_bool
\keys_define:nn { @@ / setup }
  {         
    activate/spaces .choice:,
    activate/spaces/true .code:n = 
      { \msg_warning:nne {tag}{sys-no-interwordspace}{\c_sys_engine_str}  },
    activate/spaces/false .code:n= 
      { \msg_warning:nne {tag}{sys-no-interwordspace}{\c_sys_engine_str}  },
    activate/spaces .default:n = true,    
    debug/show/spaces     .code:n = {\bool_set_true:N \l_@@_showspaces_bool},
    debug/show/spacesOff  .code:n = {\bool_set_false:N \l_@@_showspaces_bool},
%    \end{macrocode}
% deprecated versions:
%    \begin{macrocode}
    interwordspace .choices:nn = {true,on}{\keys_set:nn{@@/setup}{activate/spaces={true}}},
    interwordspace .choices:nn = {false,off}{\keys_set:nn{@@/setup}{activate/spaces={false}}},
    interwordspace .default:n = {true},
    show-spaces    .choice:,
    show-spaces/true .meta:n =  {debug/show=spaces},
    show-spaces/false .meta:n = {debug/show=spacesOff},
    show-spaces .default:n = true
  }
\sys_if_engine_pdftex:T
  {
    \sys_if_output_pdf:TF
      {
        \pdfglyphtounicode{space}{0020}
        \AddToHook{shipout/firstpage}[tagpdf/space]{}
        \keys_define:nn { @@ / setup }
          {
            activate/spaces/true .code:n  = { \AddToHook{shipout/firstpage}[tagpdf/space]{\pdfinterwordspaceon} },
            activate/spaces/false .code:n = { \RemoveFromHook{shipout/firstpage}[tagpdf/space] },
            activate/spaces .default:n = true,
          }
      }
      {
        \keys_define:nn { @@ / setup }
          {
            activate/spaces .choices:nn = { true, false }
              { \msg_warning:nnn {tag}{sys-no-interwordspace}{dvi}  },
            activate/spaces .default:n = true,
          }
      }
  }


\sys_if_engine_luatex:T
  {
    \keys_define:nn { @@ / setup }
      {
        activate/spaces .choice:,
        activate/spaces/true .code:n =                            
                                 {
                                   \bool_gset_true:N \g_@@_active_space_bool
                                   \lua_now:e{ltx.@@.func.markspaceon()}
                                 },
        activate/spaces/false .code:n =
                                 {
                                  \bool_gset_false:N \g_@@_active_space_bool
                                  \lua_now:e{ltx.@@.func.markspaceoff()}
                                 },
        activate/spaces .default:n = true,
        debug/show/spaces    .code:n =
                                 {\lua_now:e{ltx.@@.trace.showspaces=true}},
        debug/show/spacesOff .code:n =
                                 {\lua_now:e{ltx.@@.trace.showspaces=nil}},
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_fakespace:}
% For luatex we need a command for the fake space as equivalent of the pdftex
% primitive.
%    \begin{macrocode}
\sys_if_engine_luatex:T
  {
    \cs_new_protected:Nn \@@_fakespace:
      {
        \group_begin:
        \lua_now:e{ltx.@@.func.fakespace()}
        \skip_horizontal:n{\c_zero_skip}
        \group_end:
      }
  }
%    \end{macrocode}
% 
% We need also a command to interrupt the insertion of real space
% chars in places where we want to insert manually special spaces. 
% In pdftex this can be done with \cs{pdfinterwordspaceoff}
% and \cs{pdfinterwordspaceon}. These commands insert whatsits
% and this mean they act globally. In luatex a attribute is
% used to this effect, for consistency this is also set globally.
% 
%
% \begin{macro}{\tag_spacechar_on:,\tag_spacechar_off:}
% The off command sets the attributes in luatex.
%    \begin{macrocode}
\cs_new_protected:Npn \tag_spacechar_off: {}
\cs_new_protected:Npn \tag_spacechar_on: {}

\sys_if_engine_luatex:T
 {
   \cs_set_protected:Npn \tag_spacechar_off: 
     {
       \lua_now:e 
         {
           tex.setattribute
            (
             "global",
             luatexbase.attributes.g_@@_interwordspaceOff_attr,
             1
            )
         }
     }
   \cs_set_protected:Npn \tag_spacechar_on: 
     {
       \lua_now:e 
         {
           tex.setattribute
            (
             "global",
             luatexbase.attributes.g_@@_interwordspaceOff_attr,
             -2147483647
            )
         }
     }
 }
\sys_if_engine_pdftex:T
  {
    \sys_if_output_pdf:T
      {
       \cs_set_protected:Npn \tag_spacechar_off: 
          {
            \pdfinterwordspaceoff
          }       
        \cs_set_protected:Npn \tag_spacechar_on: 
          {
            \pdfinterwordspaceon
          }         
      }
  }    
%    \end{macrocode}
% \end{macro}
%    \begin{macrocode}
%</package>
%    \end{macrocode}
% \end{macro}
% \end{implementation}
% \PrintIndex
