% Copyright 2026 Open-Guji (https://github.com/open-guji)
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.

% luatex-cn-digital.sty
% Digital-specific commands for guji-digital class.
% Layout-centric commands for digitization workflow (缩进, 双列, 版心, etc.).
% DigitalContent is a backward-compatible alias for BodyText (digital-mode
% is set globally in guji-digital.cls).

\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3}
\RequirePackage{xparse}
\ProvidesExplPackage {digital/luatex-cn-digital} {2026/02/26} {0.3.1}
  {Digital-specific commands for ancient Chinese book digitization}

\RequirePackage{core/luatex-cn-core-base}
\RequirePackage{core/luatex-cn-core-textflow}

% ============================================================================
% Penalty constants
% ============================================================================
\int_const:Nn \c__luatexcn_digital_penalty_force_column_int { -10002 }
\int_const:Nn \c__luatexcn_digital_penalty_newline_int { -10005 }

% ============================================================================
% DigitalContent — backward-compatible alias for BodyText
% ============================================================================
% DigitalContent is now an alias for BodyText. The digital-mode behavior
% (obeylines, async vbox) is controlled by the digital-mode key in
% luatexcn/content, which guji-digital.cls sets globally to true.
\NewEnvironmentCopy{DigitalContent}{BodyText}

% \Indent / \缩进 is now defined in core/luatex-cn-core-paragraph.sty

% ============================================================================
% \双列{\右小列{...}\左小列{...}} — Explicit dual-column (jiazhu)
% ============================================================================
% For digitization: explicitly specify right and left sub-column content.
% Uses two consecutive TextFlow calls with only-column mode.
%
% Syntax: \双列{\右小列{right content}\左小列{left content}}

\tl_new:N \l__luatexcn_digital_right_col_tl
\tl_new:N \l__luatexcn_digital_left_col_tl
\tl_new:N \l__luatexcn_digital_right_indent_tl
\tl_new:N \l__luatexcn_digital_left_indent_tl

% Keys for sub-column options
\keys_define:nn { luatexcn / digital / subcol }
  {
    indent .tl_set:N = \l__luatexcn_digital_subcol_indent_tl,
    indent .initial:n = {},
  }

\NewDocumentCommand{\RightSubCol}{ O{} +m }
  {
    \tl_set:Nn \l__luatexcn_digital_right_col_tl { #2 }
    \tl_clear:N \l__luatexcn_digital_subcol_indent_tl
    \tl_if_empty:nF { #1 }
      { \keys_set:nn { luatexcn / digital / subcol } { #1 } }
    \tl_set_eq:NN \l__luatexcn_digital_right_indent_tl \l__luatexcn_digital_subcol_indent_tl
  }

\NewDocumentCommand{\LeftSubCol}{ O{} +m }
  {
    \tl_set:Nn \l__luatexcn_digital_left_col_tl { #2 }
    \tl_clear:N \l__luatexcn_digital_subcol_indent_tl
    \tl_if_empty:nF { #1 }
      { \keys_set:nn { luatexcn / digital / subcol } { #1 } }
    \tl_set_eq:NN \l__luatexcn_digital_left_indent_tl \l__luatexcn_digital_subcol_indent_tl
  }

\NewDocumentCommand{\DualColumn}{ +m }
  {
    \tl_clear:N \l__luatexcn_digital_right_col_tl
    \tl_clear:N \l__luatexcn_digital_left_col_tl
    \tl_clear:N \l__luatexcn_digital_right_indent_tl
    \tl_clear:N \l__luatexcn_digital_left_indent_tl
    % Execute inner commands to collect right/left content and indent
    #1
    % Output right sub-column, then left sub-column
    % TextFlow continuation mechanism: right-only ends with pending_sub_col=1,
    % so the next left-only TextFlow starts at sub_col=2 automatically.
    \tl_if_empty:NF \l__luatexcn_digital_right_col_tl
      {
        % Apply per-sub-column indent if specified
        \tl_if_empty:NF \l__luatexcn_digital_right_indent_tl
          { \exp_args:NV \__luatexcn_set_indent:n \l__luatexcn_digital_right_indent_tl }
        \TextFlow[only-column=right, auto-balance=false]{ \l__luatexcn_digital_right_col_tl }
      }
    % When left sub-column is empty but right was non-empty, insert a
    % full-width space as placeholder. This ensures the left-only TextFlow
    % produces a glyph node that consumes the pending_sub_col=1 state
    % from the right TextFlow, preventing state corruption for subsequent
    % \DualColumn calls.
    % Output left sub-column (even if empty)
    % When left is empty and right was non-empty, the empty TextFlow call
    % will trigger the pending_sub_col cleanup logic in textflow.lua:434-438,
    % which properly advances cur_row without generating any glyph nodes.
    \tl_if_empty:NTF \l__luatexcn_digital_left_col_tl
      {
        \tl_if_empty:NF \l__luatexcn_digital_right_col_tl
          {
            % Empty left column: call TextFlow with empty content to consume pending state
            \TextFlow[only-column=left, auto-balance=false]{ }
          }
      }
      {
        % Apply per-sub-column indent if specified
        \tl_if_empty:NF \l__luatexcn_digital_left_indent_tl
          { \exp_args:NV \__luatexcn_set_indent:n \l__luatexcn_digital_left_indent_tl }
        \TextFlow[only-column=left, auto-balance=false]{ \l__luatexcn_digital_left_col_tl }
      }
  }

% ============================================================================
% Banxin (版心) Environment — Explicit banxin content specification
% ============================================================================
% For digitization: explicitly specify all banxin content elements.
% This environment enables banxin and wraps sub-commands that set
% book name, chapter title, page number, publisher, and yuwei toggles.
%
% Syntax:
%   \begin{Banxin}
%     \BanxinUpper{书名}
%     \begin{BanxinMiddle}
%       \UpperYuwei
%       \BanxinChapter{章节名}
%       \BanxinPageNumber{一}
%       \LowerYuwei
%     \end{BanxinMiddle}
%     \BanxinLower{出版商}
%   \end{Banxin}

% LaTeX's \begin{...} always creates a group, so banxin sub-commands
% must use GLOBAL assignment to ensure parameters persist after \end{Banxin}.
% The Banxin/BanxinMiddle environments are provided for readability;
% sub-commands can also be used standalone outside any environment.

\NewDocumentEnvironment{Banxin}{ }
  {
    % Enable banxin and reset yuwei (global assignments inside)
    \bool_gset_true:N \l__luatexcn_banxin_on_bool
    \bool_gset_false:N \l__luatexcn_banxin_upper_yuwei_bool
    \bool_gset_false:N \l__luatexcn_banxin_lower_yuwei_bool
    % Sync to Lua
    \lua_now:n { _G.banxin.setup({~enabled~=~true~}) }
  }
  { }

\NewDocumentEnvironment{BanxinMiddle}{ }
  { }
  { }

% --- Sub-commands (use global assignment to survive groups) ---

\NewDocumentCommand{\BanxinUpper}{ m }
  {
    \tl_gset:Nn \l__luatexcn_banxin_book_name_tl { #1 }
  }

\NewDocumentCommand{\BanxinLower}{ m }
  {
    \tl_gset:Nn \l__luatexcn_banxin_publisher_tl { #1 }
  }

\NewDocumentCommand{\BanxinChapter}{ m }
  {
    \tl_gset:Nn \l__luatexcn_banxin_chapter_title_tl { #1 }
  }

\NewDocumentCommand{\BanxinPageNumber}{ m }
  {
    % Set explicit page number string in Lua global
    \lua_now:e {
      _G.banxin = _G.banxin~or~{}
      _G.banxin.explicit_page_number = [=[\luaescapestring{#1}]=]
    }
  }

\NewDocumentCommand{\UpperYuwei}{ }
  {
    \bool_gset_true:N \l__luatexcn_banxin_upper_yuwei_bool
  }

\NewDocumentCommand{\LowerYuwei}{ }
  {
    \bool_gset_true:N \l__luatexcn_banxin_lower_yuwei_bool
  }

% ============================================================================
% CJK Aliases
% ============================================================================
% Simplified Chinese
% \缩进 is defined in core/luatex-cn-core-paragraph.sty
\NewCommandCopy{\双列}{\DualColumn}
\NewCommandCopy{\右小列}{\RightSubCol}
\NewCommandCopy{\左小列}{\LeftSubCol}
% Note: 数字化内容 已废弃，请使用 \正文 (BodyText 在 digital-mode 下自动 obeylines)
\NewEnvironmentCopy{版心}{Banxin}
\NewCommandCopy{\版心上部}{\BanxinUpper}
\NewCommandCopy{\版心下部}{\BanxinLower}
\NewCommandCopy{\版心章节}{\BanxinChapter}
\NewCommandCopy{\版心页码}{\BanxinPageNumber}
\NewCommandCopy{\上鱼尾}{\UpperYuwei}
\NewCommandCopy{\下鱼尾}{\LowerYuwei}
\NewEnvironmentCopy{版心中部}{BanxinMiddle}
% \换页 must delegate to \newpage (not copy) because \newpage is
% overridden inside Content groups to emit PENALTY_FORCE_PAGE.
\NewDocumentCommand{\换页}{}{\newpage}
% Traditional Chinese (only chars that differ from simplified)
% \縮進 is defined in core/luatex-cn-core-paragraph.sty
\NewCommandCopy{\雙列}{\DualColumn}
\NewEnvironmentCopy{數字化內容}{BodyText}
\NewCommandCopy{\上魚尾}{\UpperYuwei}
\NewCommandCopy{\下魚尾}{\LowerYuwei}
\NewCommandCopy{\換頁}{\换页}

\ExplSyntaxOff
\endinput
