% 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-core-column.sty
% Column (单列排版) support for vertical typesetting
% This is a subpackage of luatex_cn
%
% Usage:
%   \Column{content}                    % Default: top alignment
%   \Column[align=center]{content}      % Center alignment
%   \Column[align=bottom]{content}      % Bottom alignment
%   \Column[align=stretch]{content}     % Stretch/squeeze to fill column
%
\RequirePackage{core/luatex-cn-core-base}
\RequirePackage{expl3}
\RequirePackage{xparse}
\ProvidesExplPackage {core/luatex-cn-core-column} {2026/02/18} {0.3.0} {Column Support for Vertical Typesetting}

% Default variables for column
\tl_new:N \l__luatexcn_column_default_size_tl
\tl_new:N \l__luatexcn_column_default_font_tl
\tl_new:N \l__luatexcn_column_default_color_tl

% Global dim for current column width (read by TextBox for inner-gw auto-calculation)
% 0pt means not set (use default grid_width)
\dim_new:N \g__luatexcn_column_current_width_dim

\makeatletter

    % Align mode: 0=top, 1=bottom, 2=center, 3=stretch
    % When last=true, add 4 to the value (4=last+top, 5=last+bottom, etc.)
    \bool_new:N \l__luatexcn_column_last_bool

    \keys_define:nn { luatexcn / column }
      {
        align .choice:,
        align / top .code:n = { \int_set:Nn \l_tmpa_int {0} },
        align / bottom .code:n = { \int_set:Nn \l_tmpa_int {1} },
        align / center .code:n = { \int_set:Nn \l_tmpa_int {2} },
        align / stretch .code:n = { \int_set:Nn \l_tmpa_int {3} },
        align .initial:n = top,

        last .bool_set:N = \l__luatexcn_column_last_bool,
        last .default:n = true,

        font-size .tl_set:N = \l__luatexcn_column_local_size_tl,
        font .tl_set:N = \l__luatexcn_column_local_font_tl,
        font-color .tl_set:N = \l__luatexcn_column_local_color_tl,

        % 列宽参数
        width .tl_set:N = \l__luatexcn_column_width_tl,
        width .initial:n = {},
        column-width .tl_set:N = \l__luatexcn_column_width_tl,  % 别名

        auto-width .bool_set:N = \l__luatexcn_column_auto_width_bool,
        auto-width .initial:n = true,

        width-scale .tl_set:N = \l__luatexcn_column_width_scale_tl,
        width-scale .initial:n = {1.2},

        % 列间距参数（竖排方向）
        spacing-top .tl_set:N = \l__luatexcn_column_spacing_top_tl,
        spacing-top .initial:n = {},

        spacing-bottom .tl_set:N = \l__luatexcn_column_spacing_bottom_tl,
        spacing-bottom .initial:n = {},

        spacing .meta:n = { spacing-top = #1, spacing-bottom = #1 },

        grid-height .tl_set:N = \l__luatexcn_column_grid_height_tl,
        grid-height .initial:n = {},
      }

    \NewDocumentCommand{\Column}{ O{} +m }
      {
        \group_begin:

        % Initialize alignment mode (0 = top/default)
        \int_set:Nn \l_tmpa_int {0}
        % Initialize last flag
        \bool_set_false:N \l__luatexcn_column_last_bool
        % Initialize local override variables
        \tl_set:Nn \l__luatexcn_column_local_size_tl {}
        \tl_set:Nn \l__luatexcn_column_local_font_tl {}
        \tl_set:Nn \l__luatexcn_column_local_color_tl {}
        \tl_set:Nn \l__luatexcn_column_width_tl {}
        \tl_set:Nn \l__luatexcn_column_grid_height_tl {}
        \bool_set_true:N \l__luatexcn_column_auto_width_bool
        \tl_set:Nn \l__luatexcn_column_width_scale_tl {1.2}
        \tl_set:Nn \l__luatexcn_column_spacing_top_tl {}
        \tl_set:Nn \l__luatexcn_column_spacing_bottom_tl {}

        \keys_set:nn { luatexcn / column } { #1 }

        % Handle column width: register in Lua and set global dim for TextBox
        \tl_if_empty:NF \l__luatexcn_column_width_tl
          {
            \dim_gset:Nn \g__luatexcn_column_current_width_dim
              { \l__luatexcn_column_width_tl }
            \lua_now:e {
              require('core.luatex-cn-core-content').register_col_width(
                \dim_to_decimal_in_sp:n { \l__luatexcn_column_width_tl })
            }
          }

        % If last=true, add 4 to align mode
        \bool_if:NT \l__luatexcn_column_last_bool
          { \int_add:Nn \l_tmpa_int {4} }

        % 1. Determine Font Size (Local > Default)
        \tl_if_empty:NTF \l__luatexcn_column_local_size_tl
          { \tl_set_eq:NN \l_tmpc_tl \l__luatexcn_column_default_size_tl }
          { \tl_set_eq:NN \l_tmpc_tl \l__luatexcn_column_local_size_tl }

        % 2. Determine Font (Local > Default)
        \tl_if_empty:NTF \l__luatexcn_column_local_font_tl
          { \tl_set_eq:NN \l_tmpb_tl \l__luatexcn_column_default_font_tl }
          { \tl_set_eq:NN \l_tmpb_tl \l__luatexcn_column_local_font_tl }

        % 3. Determine Color (Local > Default)
        \tl_if_empty:NTF \l__luatexcn_column_local_color_tl
          { \tl_set_eq:NN \l_tmpd_tl \l__luatexcn_column_default_color_tl }
          { \tl_set_eq:NN \l_tmpd_tl \l__luatexcn_column_local_color_tl }

        % Apply Font and Size if specified
        \tl_if_empty:NF \l_tmpc_tl
          {
            \tl_if_empty:NTF \l_tmpb_tl
              { \fontsize{\l_tmpc_tl}{\l_tmpc_tl}\selectfont }
              { \setmainfont{\l_tmpb_tl}[RawFeature={+vert,+vrt2}] \fontsize{\l_tmpc_tl}{\l_tmpc_tl}\selectfont }
          }

        % Apply Color (visual appearance)
        \tl_if_empty:NF \l_tmpd_tl
          {
            \tl_if_in:NnTF \l_tmpd_tl { , }
              { \color[rgb]{\l_tmpd_tl} }
              {
                \tl_if_in:NnTF \l_tmpd_tl { ~ }
                  {
                    \tl_set:Nx \l_tmpe_tl { \l_tmpd_tl }
                    \tl_replace_all:Nnn \l_tmpe_tl { ~ } { , }
                    \color[rgb]{\l_tmpe_tl}
                  }
                  { \color{\l_tmpd_tl} }
              }
          }

        % Push style to stack and get style ID
        \edef\column_style_id{\lua_now:e {
          local ~ column = require('core.luatex-cn-core-column')
          local ~ style_id = column.push_style(
            \tl_if_empty:NTF \l_tmpd_tl { nil } { [=[\luaescapestring{\tl_use:N \l_tmpd_tl}]=] },
            \tl_if_empty:NTF \l_tmpc_tl { nil } { [=[\luaescapestring{\tl_use:N \l_tmpc_tl}]=] },
            \tl_if_empty:NTF \l_tmpb_tl { nil } { [=[\luaescapestring{\tl_use:N \l_tmpb_tl}]=] },
            \tl_if_empty:NTF \l__luatexcn_column_grid_height_tl { nil } { [=[\luaescapestring{\tl_use:N \l__luatexcn_column_grid_height_tl}]=] },
            \tl_if_empty:NTF \l__luatexcn_column_spacing_top_tl { nil } { [=[\luaescapestring{\tl_use:N \l__luatexcn_column_spacing_top_tl}]=] },
            \tl_if_empty:NTF \l__luatexcn_column_spacing_bottom_tl { nil } { [=[\luaescapestring{\tl_use:N \l__luatexcn_column_spacing_bottom_tl}]=] },
            \tl_if_empty:NTF \l__luatexcn_column_width_tl { nil } { [=[\luaescapestring{\tl_use:N \l__luatexcn_column_width_tl}]=] },
            \bool_if:NTF \l__luatexcn_column_auto_width_bool { true } { false },
            \tl_if_empty:NTF \l__luatexcn_column_width_scale_tl { nil } { [=[\luaescapestring{\tl_use:N \l__luatexcn_column_width_scale_tl}]=] }
          )
          tex.print(tostring(style_id))
        }}

        % Set column attributes
        \setluatexattribute\cnverticalcolumn{1}
        \setluatexattribute\cnverticalcolumnalign{\int_use:N \l_tmpa_int}
        \setluatexattribute\cnverticalstyle{\column_style_id}

        #2
        % Insert column boundary marker (penalty -10001) for Free Mode boundary detection
        % This specific value marks column boundaries without affecting line breaking
        \penalty-10001

        % Reset column width after content
        \dim_gset:Nn \g__luatexcn_column_current_width_dim { 0pt }

        % Pop style from stack
        \lua_now:n {
          local ~ column = require('core.luatex-cn-core-column')
          column.pop_style()
        }

        \group_end:
      }

\makeatother

\ExplSyntaxOff%

% LastColumn: place content in the last column of current half-page
\ExplSyntaxOn
\NewDocumentCommand{\LastColumn}{ O{} +m }{%
  \tl_if_empty:nTF {#1}
    { \Column[last]{#2} }
    { \Column[last, #1]{#2} }
}
\ExplSyntaxOff

% ============================================================
% Chinese aliases / 中文别名
% ============================================================
% Simplified Chinese / 简体
\NewCommandCopy{\行}{\Column}
\NewCommandCopy{\末行}{\LastColumn}

% ============================================================
% Chinese key aliases / 中文 Key 别名
% ============================================================
\ExplSyntaxOn
\keys_define:nn { luatexcn / column }
  {
    % 简体
    对齐 .meta:n = { align = #1 },
    末列 .bool_set:N = \l__luatexcn_column_last_bool,
    字号 .tl_set:N = \l__luatexcn_column_local_size_tl,
    字体 .tl_set:N = \l__luatexcn_column_local_font_tl,
    字体颜色 .tl_set:N = \l__luatexcn_column_local_color_tl,
    宽度 .tl_set:N = \l__luatexcn_column_width_tl,
    列宽 .tl_set:N = \l__luatexcn_column_width_tl,
    自动宽度 .bool_set:N = \l__luatexcn_column_auto_width_bool,
    宽度缩放 .tl_set:N = \l__luatexcn_column_width_scale_tl,
    上间距 .tl_set:N = \l__luatexcn_column_spacing_top_tl,
    下间距 .tl_set:N = \l__luatexcn_column_spacing_bottom_tl,
    间距 .meta:n = { spacing-top = #1, spacing-bottom = #1 },
    格高 .tl_set:N = \l__luatexcn_column_grid_height_tl,
    % 繁体（与简体不同形的）
    對齊 .meta:n = { align = #1 },
    字號 .tl_set:N = \l__luatexcn_column_local_size_tl,
    字體 .tl_set:N = \l__luatexcn_column_local_font_tl,
    字體顏色 .tl_set:N = \l__luatexcn_column_local_color_tl,
    寬度 .tl_set:N = \l__luatexcn_column_width_tl,
    列寬 .tl_set:N = \l__luatexcn_column_width_tl,
    自動寬度 .bool_set:N = \l__luatexcn_column_auto_width_bool,
    寬度縮放 .tl_set:N = \l__luatexcn_column_width_scale_tl,
    上間距 .tl_set:N = \l__luatexcn_column_spacing_top_tl,
    下間距 .tl_set:N = \l__luatexcn_column_spacing_bottom_tl,
    間距 .meta:n = { spacing-top = #1, spacing-bottom = #1 },
  }
\ExplSyntaxOff

\endinput%
