% \iffalse meta-comment % !TeX program = XeLaTeX % !TeX encoding = UTF-8 %<*internal> \iffalse % %<*readme> wrapstuff ========= The `wrapstuff` package provides another implementation of text wrapping. Its implementation benefits from the paragraph hooks available since LaTeX 2021-06-01. Basic Usage ----------- The package only provides a user environment `wrapstuff`. \begin{wrapstuff}[] \end{wrapstuff}
You can read the package manual (in Chinese) for some explanations. Contributing ------------ The package is still highly experimental and not fully tested. [Issues](https://github.com/qinglee/wrapstuff/issues) and [pull requests](https://github.com/qinglee/wrapstuff/pulls) are always welcome. Copyright and Licence --------------------- Copyright (C) 2022 by Qing Lee ----------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. This package consists of the file wrapstuff.dtx, and the derived files wrapstuff.pdf, wrapstuff.sty, wrapstuff.ins and README.md (this file). % %<*internal> \fi \begingroup \def\temp{LaTeX2e} \expandafter\endgroup\ifx\temp\fmtname\else \csname fi\endcsname % %<*install> \input ctxdocstrip % \preamble Copyright (C) 2022 by Qing Lee ----------------------------------------------------------------- This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3c of this license or (at your option) any later version. This version of this license is in http://www.latex-project.org/lppl/lppl-1-3c.txt and the latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. This work has the LPPL maintenance status "maintained". The Current Maintainer of this work is Qing Lee. ----------------------------------------------------------------- \endpreamble \postamble This work consists of the file wrapstuff.dtx, and the derived files wrapstuff.pdf, wrapstuff.sty, wrapstuff.ins and README.md. \endpostamble \generate { % %<*internal> \usedir{source/latex/wrapstuff} \file{wrapstuff.ins} {\from{\jobname.dtx}{install}} % %<*install> \usedir{tex/latex/wrapstuff} \file{wrapstuff.sty} {\from{\jobname.dtx}{package}} \nopreamble\nopostamble \usedir{doc/latex/wrapstuff} \file{README.md} {\from{\jobname.dtx}{readme}} } \endbatchfile % %<*internal> \fi % %\NeedsTeXFormat{LaTeX2e}[2021-06-01] %\@ifundefined{ExplLoaderFileDate}{\RequirePackage{expl3}}{} %<+package>\GetIdInfo$Id: wrapstuff.dtx 3be38c0 2022-08-05 21:01:02 +0800 Qing Lee $ % {Wrapping text around stuff} %\ProvidesExplPackage{\ExplFileName} % {\ExplFileDate}{0.3}{\ExplFileDescription} %<*driver> \documentclass{ctxdoc} \usepackage{wrapstuff} \usepackage{graphicx} \usepackage{zhlipsum} \ExplSyntaxOn \makeatletter \DeclareDocumentCommand \gitsha { m } { \href { https \c_colon_str //github.com/qinglee/wrapstuff/commit/#1 } { rev. ~ \texttt{#1} } } \DeclareDocumentCommand \QIANZIWEN { } { 天地玄黄宇宙洪荒日月盈昃辰宿列张 寒来暑往秋收冬藏闰馀成岁律召调阳 \par 云腾致雨露结为霜金生丽水玉出昆冈 \par } \DeclareDocumentCommand \ADDSPECEIALKEY { m } { \cs_gset_eq:NN \@@_codedoc_names_typeset_save: \__codedoc_names_typeset: \cs_gset_protected:Npn \__codedoc_names_typeset: { \cs_gset_eq:NN \__codedoc_names_typeset: \@@_codedoc_names_typeset_save: \__codedoc_names_typeset: #1 \\ } } \DeclareDocumentCommand \IMAGE { m m } { \includegraphics [ width = \dim_eval:n {#1} ] { example-image-#2.pdf } } \tl_put_left:Nn \Example { \trivlist \item \relax } \tl_put_right:Nn \endExample { \endtrivlist } \SideBySideExampleSet { numbers = none } \makeatother \ExplSyntaxOff \begin{document} \DocInput{\jobname.dtx} \IndexLayout \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{3127} % % \changes{v0.1}{2022/07/05}{初始版本。} % \changes{v0.1}{2022/07/20}{首次提交到 CTAN 发布。} % \changes{v0.2}{2022/07/21}{改进放置方式。} % % \GetFileId{wrapstuff.sty} % % \title{\bfseries\pkg{wrapstuff} 宏包} % \author{李清} % \date{\filedate\qquad\fileversion\thanks{\gitsha{\ExplFileVersion}.}} % \maketitle % % \begin{documentation} % % \section{基本用法} % % \pkg{wrapstuff} 宏包提供了图文绕排的另一种实现。 % \pkg{wrapstuff} 尝试整合和扩展 \pkg{picinpar}、\pkg{floatflt}、\pkg{wrapfig}、 % \pkg{cutwin} 和 \pkg{wrapfig2} 等同类宏包的功能。 % 本宏包兼容 \pkg{caption}、\pkg{float} 和 \pkg{floatrow} 等宏包, % 并试图兼容显示(display)数学公式和各种 \LaTeX\ 列表环境,可以让他们正确绕排。 % % \pkg{wrapstuff} 的实现依赖 \LaTeX\ 2021-06-01 开始提供的段落钩子, % 并依赖 \LaTeXiii\ 2022-04-10 之后的版本。 % % \begin{function}{wrapstuff} % \begin{syntax} % \tn{begin}\{wrapstuff\}\oarg{选项} % <绕排内容> % \tn{end}\{wrapstuff\} % <正文> % \end{syntax} % \pkg{wrapstuff} 只提供了一个用户环境 \env{wrapstuff}, % 会在环境之后的段落开始绕排。例如 % \begin{Example}[frame=single,numbers=none,gobble=5] % \begin{wrapstuff}[c,top=1] % \includegraphics[width=\dimeval{\linewidth/3}]{example-image.pdf} % \end{wrapstuff} % \zhlipsum[1][name=zhufu] % \end{Example} % \end{function} % % \begin{function}{\wrapstuffset} % \begin{syntax} % \tn{wrapstuffset} \Arg{选项列表} % \end{syntax} % \pkg{wrapstuff} 的选项可以在调用宏包时设置,也可以通过 \tn{wrapstuffset} 设置。 % 选项将在下面描述。 % \end{function} % % \ADDSPECEIALKEY{\textrm{\meta{n}}} % \begin{function}{top} % \begin{syntax} % top = <非负整数> % \end{syntax} % 设置在正文段落的第几行之后开始绕排,可以设置为非负整数。 % 非负整数选项 \meta{n} 是设置选项 \opt{top} 为 \meta{n} 的缩写形式。 % 初始值是 \num{0}。 % \end{function} % % \begin{function}{width} % \begin{syntax} % width = <宽度> % \end{syntax} % 设置绕排内容的宽度,初始值为 \qty{0}{pt},代表自然宽度。 % 此时,\env{wrapstuff} 环境内的内容只能有一行,不能使用 |\\| 换行或者 \tn{par} 分段。 % 如果需要在环境内换行或者分段,就需要将 \opt{width} 设置成合适的宽度。 % \end{function} % % \begin{function}{height} % \begin{syntax} % height = <高度> % \end{syntax} % 设置绕排内容的高度,初始值为 \qty{0}{pt},代表自然高度。 % \end{function} % % \begin{function}{lines} % \begin{syntax} % lines = <正整数> % \end{syntax} % 设置绕排内容占据正文的行数,可以设置正整数。 % 初始值为空,根据绕排内容的高度自动计算行数。 % \end{function} % % \begin{function}{linewidth} % \begin{syntax} % linewidth = <宽度> % \end{syntax} % 设置正文段落的行宽,初始设置为 |\linewidth|,一般不需要调整。 % \end{function} % % \begin{function}{l,r,c,i,o,ratio} % \begin{syntax} % l/r/c/i/o % ratio = <实数> % \end{syntax} % 这些选项用于设置绕排内容位于正文中的位置。 % 选项 \opt{l/r/c/i/o} 分别设置绕排内容位于正文的左侧、右侧、中间、内侧、外侧。 % 选项 \opt{ratio} 设置绕排内容左侧的正文占据行宽的比例,可以设置为 $[0,1]$ 区间中的合理实数。 % 选项 \opt{i/o} 可以与 \opt{ratio} 一起使用,这时设置的是内/外侧正文的行宽比例。 % 初始设置为 |r|,即位于正文的右侧。 % \end{function} % % \begin{function}{column} % \begin{syntax} % column = <(true)|false|par> % \end{syntax} % 控制是否将绕排内容两侧的正文分栏显示,只有设置 |c| 选项或者 % 设置 \opt{ratio} 不等于 $0$ 或者 $1$ 时才有效。 % \opt{false} 表示不分栏,正文文字方向始终保持从左到右的顺序; % \opt{par} 表示以段落为单位进行分栏,如下示例。 % \begin{SideBySideExample}[xrightmargin=\dimeval{20em+5mm}] % \begin{wrapstuff}[c,1] % \IMAGE{2em}{a} % \end{wrapstuff} % \QIANZIWEN % \begin{wrapstuff}[c,1,column=par] % \IMAGE{2em}{b} % \end{wrapstuff} % \QIANZIWEN % \begin{wrapstuff}[c,0,column=false] % \IMAGE{2em}{c} % \end{wrapstuff} % \QIANZIWEN % \end{SideBySideExample} % \end{function} % % \begin{function}{leftsep,rightsep,hsep} % \begin{syntax} % leftsep = <长度> % rightsep = <长度> % hsep = <长度> % \end{syntax} % 设置绕排内容与正文的左/右间距,选项 \opt{hsep} 同时设置 \opt{leftsep} 和 \opt{rightsep}。 % 初始值是 \qty{1}{em}。 % \end{function} % % \begin{function}{abovesep,belowsep,vsep} % \begin{syntax} % abovesep = <长度> % belowsep = <长度> % vsep = <长度> % \end{syntax} % 设置绕排内容与正文的上/下间距,选项 \opt{vsep} 同时设置 \opt{abovesep} 和 \opt{belowsep}。 % 初始值是 \qty{0}{pt}。 % \end{function} % % \begin{function}{hoffset} % \begin{syntax} % hoffset = <长度> % \end{syntax} % 设置绕排内容伸出正文版心的长度。 % 当设置了选项 \opt{c} 或者选项 \opt{ratio} 的值位于 $(0,1)$ 时,本选项无效。 % 一个特殊值 \tn{width} 用于表示绕排内容和相应间距的总宽度, % 可以将 \opt{hoffset} 设置为 \tn{width},完全伸出版心。 % 初始值为 \qty{0}{pt}。 % \end{function} % % \begin{function}{voffset} % \begin{syntax} % voffset = <长度> % \end{syntax} % 用于调整绕排内容的竖直位置,初始值为 \qty{0}{pt}。 % \end{function} % % \begin{function}{type} % \begin{syntax} % type = <浮动体类型> % \end{syntax} % 设置绕排内容的浮动体类型,初始值为空。 % 如果需要在 \env{wrapstuff} 环境中使用 \tn{caption} 命令, % 则需要设置 \opt{type} 为 \opt{figure} 或 \opt{table} 等类型, % 并需要同时设置 \opt{width} 指定宽度。 % \begin{SideBySideExample}[xrightmargin=\dimeval{18em+5mm}] % \begin{wrapstuff}[type=figure,width=5em] % \centering % \IMAGE{4em}{plain} % \caption{示例} % \end{wrapstuff} % \QIANZIWEN % \end{SideBySideExample} % \end{function} % % \begin{function}{\wrapstuffclear} % 如果当前正文段落的行数不够,\pkg{wrapstuff} 的作用会延续到下一段。 % 这可能会导致某些意外结果,可以在下一段之前启用命令 \tn{wrapstuffclear} 消除影响。 % \end{function} % % \end{documentation} % % % \StopEventually{} % % %\begin{implementation} % % \section{代码实现} % % \begin{macrocode} %<*package> % \end{macrocode} % % \begin{macrocode} %<@@=wstf> % \end{macrocode} % % \pkg{wrapstuff} 的实现依赖 \LaTeX\ 2021-06-01 开始提供的段落钩子。 % \begin{macrocode} \@ifl@t@r \fmtversion { 2021-06-01 } { } { \msg_new:nnn { wrapstuff } { latex-too-old } { You~need~to~update~your~LaTeX~to~the~latest~release. \\ Loading~wrapstuff~will~abort! } \msg_critical:nn { wrapstuff } { latex-too-old } } % \end{macrocode} % % 由于使用了 \cs{keys_precompile:nnN},需要比较新的 \LaTeXiii。 % \begin{macrocode} \@ifl@t@r \ExplLoaderFileDate { 2022-04-10 } { } { \msg_new:nnn { wrapstuff } { latex3-too-old } { You~need~to~update~your~installation~of~the~bundles~ "l3kernel"~and~"l3packages". \\ Loading~wrapstuff~will~abort! } \msg_critical:nn { wrapstuff } { latex3-too-old } } % \end{macrocode} % % \begin{macrocode} \prop_gput:Nnn \g_msg_module_name_prop { wstf } { wrapstuff } % \end{macrocode} % % \begin{macro}[var]{ % \c_@@_global_tl_tl, % \c_@@_global_dim_tl, % \c_@@_global_int_tl, % \c_@@_global_bool_tl} % 一些需要全局设置的变量。 % \begin{macrocode} \tl_const:Nn \c_@@_global_tl_tl { \g_@@_main_setting_tl } \tl_const:Nn \c_@@_global_dim_tl { \g_@@_hang_ht_dim \g_@@_total_ht_dim \g_@@_stuff_ht_dim \g_@@_stuff_wd_dim \g_@@_first_dp_dim \g_@@_first_sep_dim \g_@@_prevdepth_dim \g_@@_column_ht_dim \g_@@_window_ht_dim \g_@@_remaining_dim \g_@@_column_room_dim \g_@@_parshape_indent_dim \g_@@_parshape_length_dim } \tl_const:Nn \c_@@_global_int_tl { \g_@@_top_int \g_@@_column_int \g_@@_window_int } \tl_const:Nn \c_@@_global_bool_tl { \g_@@_next_bool \g_@@_leqno_bool \g_@@_column_bool \g_@@_entire_bool \g_@@_display_bool \g_@@_move_hang_bool \g_@@_next_hang_bool \g_@@_first_set_bool \g_@@_first_save_bool \g_@@_right_move_bool } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_tl_init:N, % \@@_dim_init:N, % \@@_int_init:N, % \@@_bool_init:N} % 全局变量的初始化,注意保存好清除和恢复的设置。 % \begin{macrocode} \cs_new_protected:Npn \@@_tl_init:N #1 { \tl_new:N #1 \tl_gput_right:Nn \g_@@_var_clear_tl { \tl_gclear:N #1 } \tl_gput_right:Nn \g_@@_var_push_tl { \tl_gset:Nn \exp_not:N #1 { \exp_not:o {#1} } } } \cs_new_protected:Npn \@@_dim_init:N #1 { \dim_new:N #1 \tl_gput_right:Nn \g_@@_var_clear_tl { \dim_gzero:N #1 } \tl_gput_right:Nn \g_@@_var_push_tl { \dim_gset:Nn #1 { \dim_use:N #1 } } } \cs_new_protected:Npn \@@_int_init:N #1 { \int_new:N #1 \tl_gput_right:Nn \g_@@_var_clear_tl { \int_gzero:N #1 } \tl_gput_right:Nn \g_@@_var_push_tl { \int_gset:Nn #1 { \int_use:N #1 } } } \cs_new_protected:Npn \@@_bool_init:N #1 { \bool_new:N #1 \tl_gput_right:Nn \g_@@_var_clear_tl { \bool_gset_false:N #1 } \tl_gput_right:Nn \g_@@_var_push_tl { \bool_if:NTF #1 { \bool_gset_true:N #1 } { \bool_gset_false:N #1 } } } \tl_new:N \g_@@_var_clear_tl \tl_new:N \g_@@_var_push_tl \tl_map_function:NN \c_@@_global_tl_tl \@@_tl_init:N \tl_map_function:NN \c_@@_global_dim_tl \@@_dim_init:N \tl_map_function:NN \c_@@_global_int_tl \@@_int_init:N \tl_map_function:NN \c_@@_global_bool_tl \@@_bool_init:N % \end{macrocode} % \cs{g_@@_top_int} 的初始值是 $-1$。 % \begin{macrocode} \int_gdecr:N \g_@@_top_int \tl_gput_right:Nn \g_@@_var_clear_tl { \int_gdecr:N \g_@@_top_int } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_clear:, % \@@_clear_variable:, % \@@_clear_kludge:, % \@@_clear_stuff_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_clear: { \@@_clear_para_hook: \@@_clear_kludge: \@@_clear_variable: } \cs_new_protected_nopar:Npn \@@_clear_variable: { \tl_use:N \g_@@_var_clear_tl \box_gclear:N \g_@@_stuff_box } \cs_new_protected_nopar:Npn \@@_clear_kludge: { \bool_if:NTF \g_@@_next_bool { \skip_vertical:n { \tex_baselineskip:D * \g_@@_window_int } } { \box_if_empty:NF \g_@@_stuff_box { \@@_clear_stuff_box: } } } \cs_new_protected_nopar:Npn \@@_clear_stuff_box: { \@@_ignore_depth: \skip_set:Nn \l_@@_last_skip { \box_dp:N \strutbox } \skip_vertical:N \l_@@_last_skip \box_use_drop:N \g_@@_stuff_box \skip_vertical:N \l_@@_last_skip \@@_ignore_depth: } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_status_push:, % \@@_status_pop:, % \@@_status_restore:, % \@@_status_clear:} % 全局变量的保存与恢复。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_status_push: { \tl_clear:N \l_@@_status_tl \int_gincr:N \g_@@_status_int \exp_args:Ne \@@_status_push_aux:n { \int_use:N \g_@@_status_int } \seq_gpush:No \g_@@_status_seq { \l_@@_status_tl } } \cs_new_protected:Npn \@@_status_push_aux:n #1 { \@@_push_cs:nN {#1} \@@_para_before: \@@_push_cs:nN {#1} \@@_para_begin: \@@_push_cs:nN {#1} \@@_para_end: \@@_push_cs:nN {#1} \@@_display_hook: \@@_push_box:N \g_@@_stuff_box \@@_push_var: } \cs_new_protected:Npn \@@_push_cs:nN #1#2 { \exp_args:NNc \@@_push_cs_aux:NN #2 { @@_ #1 _ \token_to_str:N #2 } } \cs_new_protected:Npn \@@_push_cs_aux:NN #1#2 { \cs_gset_eq:NN #2#1 \tl_put_right:Nn \l_@@_status_tl { \cs_gset_eq:NN #1#2 \cs_undefine:N #2 } } \cs_new_protected:Npn \@@_push_box:N #1 { \hbox_gset:Nn \g_@@_stauts_box { \hbox_unpack_drop:N \g_@@_stauts_box \box_use:N #1 } \tl_put_right:Nn \l_@@_status_tl { \@@_pop_box:N #1 } } \cs_new_protected:Npn \@@_pop_box:N #1 { \hbox_gset:Nw \g_@@_stauts_box \hbox_unpack_drop:N \g_@@_stauts_box \box_gset_to_last:N #1 \@@_if_last_hlist:TF { \hbox_gset_end: } { \hbox_gset_end: \box_gclear:N \g_@@_stauts_box } } \cs_new_protected_nopar:Npn \@@_push_var: { \tl_put_right:Nx \l_@@_status_tl { \g_@@_var_push_tl } } \cs_new_protected_nopar:Npn \@@_status_pop: { \seq_gpop:NNT \g_@@_status_seq \l_@@_status_tl { \int_gdecr:N \g_@@_status_int \tl_use:N \l_@@_status_tl } } \cs_new_protected_nopar:Npn \@@_status_restore: { \@@_status_push: \@@_clear_para_hook: \@@_clear_display_hook: \@@_clear_variable: \group_insert_after:N \@@_status_pop: } \cs_new_protected_nopar:Npn \@@_status_clear: { \bool_if:NT \g_@@_next_bool { \@@_clear_para_hook: \@@_clear_variable: } } \tl_new:N \l_@@_status_tl \box_new:N \g_@@_stauts_box \int_new:N \g_@@_status_int \seq_new:N \g_@@_status_seq % \end{macrocode} % \end{macro} % % \changes{v0.2}{2022/07/21}{兼容 \tn{parbox} 与 \env{minipage} 等使用环境。} % % \begin{macro}{\wrapstuff@parboxrestore,\@arrayparboxrestore} % 在 \LaTeX\ 的 \cs{parbox} 和 \env{minipage} 等环境中恢复正常的段落状态。 % \tn{wrapstuff@parboxrestore} 的初始值是在分组后清除活动的段落钩子和相关全局变量, % 只有在 \env{wrapstuff@par} 环境内部才等于 \cs{@@_status_restore:}, % 保存和恢复相关状态。 % \begin{macrocode} \cs_new_protected_nopar:Npn \wrapstuff@parboxrestore { \group_insert_after:N \@@_status_clear: } \cs_new_protected_nopar:Npn \@@_parbox_restore: { \cs_set_eq:NN \wrapstuff@parboxrestore \@@_status_restore: } \g@addto@macro \@arrayparboxrestore { \wrapstuff@parboxrestore } % \end{macrocode} % \end{macro} % % \begin{macro}[TF]{ % \@@_if_last_none:, % \@@_if_last_hlist:, % \@@_if_last_whatsit:, % \@@_if_last_glue:, % \@@_if_last_kern:, % \@@_if_last_penalty:} % 一些 \hologo{eTeX} 结点判定函数。 % \begin{macrocode} \group_begin: \cs_set:Npn \@@_tmp:nn #1 { \exp_args:Ncc \@@_tmp_aux:NNn { @@_if_last_ #1 : } { c_@@_ #1 _node } } \cs_set:Npn \@@_tmp_aux:NNn #1#2#3 { \int_const:Nn #2 {#3} \prg_new_conditional:Npnn #1 { T , F , TF } { \if_int_compare:w \tex_lastnodetype:D = #2 \prg_return_true: \else: \prg_return_false: \fi: } } \@@_tmp:nn { none } { -1 } \@@_tmp:nn { hlist } { 1 } \@@_tmp:nn { whatsit } { 9 } \@@_tmp:nn { glue } { 11 } \@@_tmp:nn { kern } { 12 } \@@_tmp:nn { penalty } { 13 } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_gadd_hook:nn, \@@_package_hook:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_gadd_hook:nn #1 { \hook_gput_code:nnn {#1} { wrapstuff } } \cs_new_protected:Npn \@@_package_hook:nn #1 { \hook_gput_code:nnn { package/#1/after } { wrapstuff } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_para_raw_end:} % 将 \cs{para_raw_end:} 放在分组中是为了保持 \tn{parshape}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_para_raw_end: { \group_begin: \para_raw_end: \group_end: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_gadd_ht:Nn} % \begin{macrocode} \cs_new_protected:Npn \@@_gadd_ht:Nn #1#2 { \box_gset_ht:Nn #1 { \box_ht:N #1 + \dim_eval:n {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{wrapstuff} % 主要功能环境接口。 % \begin{macrocode} \NewDocumentEnvironment { wrapstuff } { O { } } { \@@_clear: \int_set:Nn \l_@@_top_int { -1 } \tl_if_blank:nTF {#1} { \tl_clear:N \l_@@_main_kv_tl } { \keys_set_filter:nnnN { wrapstuff } { main , ratio } {#1} \l_@@_main_kv_tl } \tl_set:Nx \l_@@_type_tl { \l_@@_type_tl } \dim_set:Nn \l_@@_width_dim { \l_@@_width_tl } \dim_set:Nn \l_@@_height_dim { \l_@@_height_tl } \hbox_gset:Nw \g_@@_stuff_box \dim_compare:nNnTF \l_@@_width_dim > \c_zero_dim { \@@_minipage_begin: } { \@@_hbox_begin: } } { \dim_compare:nNnTF \l_@@_width_dim > \c_zero_dim { \@@_minipage_end: } { \@@_hbox_end: } \@@_set_vsep: \@@_attach_label: \tl_if_empty:NTF \l_@@_main_kv_tl { \tl_gclear:N \g_@@_main_setting_tl } { \@@_save_main_setting: } \@@_set_top_line: \dim_gset:Nn \g_@@_stuff_wd_dim { \box_wd:N \g_@@_stuff_box } \dim_gset:Nn \g_@@_stuff_ht_dim { \box_ht_plus_dp:N \g_@@_stuff_box } \dim_gset_eq:NN \g_@@_remaining_dim \g_@@_stuff_ht_dim \@@_next_para: } \@@_gadd_hook:nn { env/wrapstuff/before } { \par } \cs_new_protected_nopar:Npn \@@_minipage_begin: { \@@_floatrow_hook: \dim_compare:nNnTF \l_@@_height_dim > \c_zero_dim { \begin { minipage } [b] [ \l_@@_height_dim ] [c] { \l_@@_width_dim } } { \begin { minipage } [b] { \l_@@_width_dim } } \tl_if_empty:NF \l_@@_type_tl { \@@_set_float: } } \cs_new_protected_nopar:Npn \@@_minipage_end: { \end { minipage } \hbox_gset_end: \@@_float_pos_hook: } \cs_new_protected_nopar:Npn \@@_hbox_begin: { \tex_ignorespaces:D } \cs_new_protected_nopar:Npn \@@_hbox_end: { \tex_unskip:D \hbox_gset_end: \dim_compare:nNnT \l_@@_height_dim > \c_zero_dim { \@@_gset_height: } } \cs_new_protected_nopar:Npn \@@_gset_height: { \hbox_gset:Nn \g_@@_stuff_box { \box_move_up:nn { ( \l_@@_height_dim - \box_ht:N \g_@@_stuff_box + \box_dp:N \g_@@_stuff_box ) / 2 } { \box_use_drop:N \g_@@_stuff_box } } \box_gset_ht:Nn \g_@@_stuff_box { \l_@@_height_dim } \box_gset_dp:Nn \g_@@_stuff_box { \c_zero_dim } } \cs_new_protected_nopar:Npn \@@_set_vsep: { \@@_gadd_ht:Nn \g_@@_stuff_box { \l_@@_abovesep_tl } \dim_set:Nn \l_@@_shift_dim { \l_@@_belowsep_tl } \dim_compare:nNnF \l_@@_shift_dim = \c_zero_dim { \@@_set_belowsep: } } \cs_new_protected_nopar:Npn \@@_set_belowsep: { \hbox_gset:Nn \g_@@_stuff_box { \box_move_up:nn { \l_@@_shift_dim + \box_dp:N \g_@@_stuff_box } { \box_use_drop:N \g_@@_stuff_box } } \box_gset_dp:Nn \g_@@_stuff_box { \c_zero_dim } } \tl_new:N \l_@@_main_kv_tl \box_new:N \g_@@_stuff_box \dim_new:N \l_@@_shift_dim \dim_new:N \l_@@_width_dim \dim_new:N \l_@@_height_dim % \end{macrocode} % \end{macro} % % \changes{v0.2}{2022/07/26}{优化重新编译警告。} % % \begin{macro}{\@@_attach_label:, \@@_write_label:,\@@_rerun_check:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_attach_label: { \stepcounter { wrapstuff } \hbox_gset:Nn \g_@@_stuff_box { \@@_write_label: \box_use_drop:N \g_@@_stuff_box } } \cs_new_protected_nopar:Npn \@@_write_label: { \exp_args:Nee \@@_write_label_aux:nn { \@@_counter:n { wrapstuff } } { \@@_counter:n { page } } } \cs_new_protected:Npx \@@_write_label_aux:nn #1#2 { \prop_gput_if_new:Nnn \exp_not:N \g_@@_page_prop {#1} {#2} \iow_shipout_x:Nn \exp_not:N \@auxout { \c_backslash_str wrapstuff@label {#1} { \exp_not:N \wrapstuff@counter { page } } } } \newcounter { wrapstuff } \cs_new:Npn \@@_counter:n #1 { \int_value:w \value {#1} } \cs_new_eq:NN \wrapstuff@counter \@@_counter:n \cs_new_protected_nopar:Npn \wrapstuff@label { \prop_gput:Nnn \g_@@_page_prop } \@@_gadd_hook:nn { begindocument } { \legacy_if:nTF { @filesw } { \iow_now:Nx \@mainaux { \c_backslash_str providecommand \c_backslash_str wrapstuff@label [2] { } } } { \cs_gset_eq:NN \@@_write_label: \@@_empty: } } \@@_gadd_hook:nn { enddocument/afterlastpage } { \legacy_if:nT { @filesw } { \prop_gclear:N \g_@@_page_prop } } \@@_gadd_hook:nn { enddocument/info } { \prop_if_empty:NF \g_@@_rerun_prop { \@@_rerun_check: } } \cs_new_protected_nopar:Npn \@@_rerun_check: { \prop_map_inline:Nn \g_@@_rerun_prop { \prop_get:NnN \g_@@_page_prop { ##1 } \l_@@_page_tl \int_if_even:nF { \l_@@_page_tl - ##2 } { \prop_map_break:n { \@@_rerun_warning: } } } } \cs_new_protected_nopar:Npn \@@_rerun_warning: { \msg_warning:nn { wstf } { rerun-required } } \msg_new:nnn { wstf } { rerun-required } { Page(s)~may~have~changed.\\ Rerun~to~get~i/o~setting~right. } \tl_new:N \l_@@_page_tl \prop_new:N \g_@@_page_prop \prop_new:N \g_@@_rerun_prop % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_save_main_setting:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_save_main_setting: { \exp_args:Nnno \keys_set_filter:nnnN { wrapstuff } { main } { \l_@@_main_kv_tl } \l_@@_main_kv_tl \bool_if:NTF \l_@@_swap_bool { \@@_swap_ratio: } { \@@_set_ratio:N \l_@@_ratio_fp } \tl_if_empty:NF \l_@@_main_kv_tl { \@@_save_main_setting_aux: } } \cs_new_protected:Npn \@@_set_ratio:N #1 { \tl_gset:Nx \g_@@_main_setting_tl { \fp_set:Nn \exp_not:N \l_@@_ratio_fp { \fp_use:N #1 } } } \cs_new_protected:Npn \@@_set_ratio:n #1 { \tl_gset:Nx \g_@@_main_setting_tl { \fp_set:Nn \exp_not:N \l_@@_ratio_fp { \fp_eval:n {#1} } } } \cs_new_protected_nopar:Npn \@@_save_main_setting_aux: { \exp_args:Nno \keys_precompile:nnN { wrapstuff } { \l_@@_main_kv_tl } \l_@@_main_kv_tl \tl_gconcat:NNN \g_@@_main_setting_tl \g_@@_main_setting_tl \l_@@_main_kv_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_top_line:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_top_line: { \int_compare:nNnF \l_@@_top_int < \c_zero_int { \tl_gput_right:Nx \g_@@_main_setting_tl { \int_set:Nn \l_@@_top_int { \int_use:N \l_@@_top_int } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_swap_ratio:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_swap_ratio: { \exp_args:Ne \@@_swap_ratio_aux:n { \@@_counter:n { wrapstuff } } } \cs_new_protected:Npn \@@_swap_ratio_aux:n #1 { \fp_compare:nF { \c_zero_fp < \l_@@_ratio_fp < \c_one_fp } { \fp_zero:N \l_@@_ratio_fp } \prop_get:NnNF \g_@@_page_prop {#1} \l_@@_page_tl { \tl_set:Nx \l_@@_page_tl { \@@_counter:n { page } } } \int_if_odd:nTF { \l_@@_page_tl } { \bool_if:NTF \l_@@_inner_bool } { \bool_if:NTF \l_@@_outer_bool } { \@@_set_ratio:N \l_@@_ratio_fp } { \@@_set_ratio:n { \c_one_fp - \l_@@_ratio_fp } } \prop_gput:Nno \g_@@_rerun_prop {#1} { \l_@@_page_tl } } \bool_new:N \l_@@_swap_bool \bool_new:N \l_@@_inner_bool \bool_new:N \l_@@_outer_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_next_para:} % 将 \env{wrapstuff} 环境之后的段落放入内部环境 \env{wrapstuff@par} 中。 % 为了控制钩子执行顺序,需要使用 |wrapstuff| 标签, % 而不用更为方便的 \cs{hook_gput_next_code:nn} 实现。 % \begin{macrocode} \@@_gadd_hook:nn { para/before } { \@@_para_before: } \@@_gadd_hook:nn { para/after } { \@@_para_after: } \@@_gadd_hook:nn { para/begin } { \@@_para_begin: } \@@_gadd_hook:nn { para/end } { \@@_para_end: } \cs_new_protected_nopar:Npn \@@_next_para: { \cs_gset_eq:NN \@@_para_before: \@@_env_before: \cs_gset_eq:NN \@@_para_begin: \@@_env_begin: \cs_gset_eq:NN \@@_para_end: \@@_env_end: } \cs_new_protected_nopar:Npn \@@_env_before: { \dim_gset_eq:NN \g_@@_prevdepth_dim \tex_prevdepth:D } \cs_new_protected_nopar:Npn \@@_env_begin: { \begin { wrapstuff@par } } \cs_new_protected_nopar:Npn \@@_env_end: { \end { wrapstuff@par } } \cs_new_protected_nopar:Npn \@@_clear_para_hook: { \cs_gset_eq:NN \@@_para_before: \@@_empty: \cs_gset_eq:NN \@@_para_after: \@@_empty: \cs_gset_eq:NN \@@_para_begin: \@@_empty: \cs_gset_eq:NN \@@_para_end: \@@_empty: } \cs_new_protected_nopar:Npn \@@_empty: { } \cs_new_eq:NN \@@_para_before: \@@_empty: \cs_new_eq:NN \@@_para_after: \@@_empty: \cs_new_eq:NN \@@_para_begin: \@@_empty: \cs_new_eq:NN \@@_para_end: \@@_empty: % \end{macrocode} % \end{macro} % % \begin{macro}[int]{wrapstuff@par} % 内部环境,实现主要功能。 % \begin{macrocode} \NewDocumentEnvironment { wrapstuff@par } { } { \tl_use:N \g_@@_main_setting_tl \dim_set:Nn \l_@@_leftsep_dim { \l_@@_leftsep_tl } \dim_set:Nn \l_@@_rightsep_dim { \l_@@_rightsep_tl } \dim_set:Nn \l_@@_voffset_dim { \l_@@_voffset_tl } \dim_set:Nn \l_@@_line_dim { \l_@@_linewidth_tl } \dim_set:Nn \l_@@_min_dim { \box_dp:N \strutbox } \dim_set_eq:NN \l_@@_main_width_dim \l_@@_line_dim \dim_sub:Nn \l_@@_line_dim { \tex_leftskip:D + \tex_rightskip:D } \dim_set:Nn \l_@@_window_dim { \l_@@_line_dim - \g_@@_stuff_wd_dim } \fp_compare:nNnTF \l_@@_ratio_fp > \c_zero_fp { \fp_compare:nNnTF \l_@@_ratio_fp < \c_one_fp { \@@_set_window: } { \@@_set_hang_right: } } { \@@_set_hang_left: } \int_compare:nNnTF \g_@@_window_int > \c_zero_int { \int_set_eq:NN \l_@@_window_int \g_@@_window_int \int_zero:N \l_@@_top_int } { \@@_set_lines: } \bool_if:NTF \l_@@_hang_bool { \dim_set_eq:NN \l_@@_display_dim \l_@@_window_dim \int_set_eq:NN \l_@@_window_line_int \l_@@_window_int } { \dim_set_eq:NN \l_@@_display_dim \l_@@_l_dim \int_set:Nn \l_@@_window_int { \l_@@_window_int * 2 } \int_set:Nn \l_@@_window_line_int { \bool_if:NTF \g_@@_column_bool { \l_@@_window_int / 2 + \g_@@_column_int } { \l_@@_window_int } } } \cs_gset_eq:NN \@@_para_before: \@@_empty: \cs_gset_eq:NN \@@_para_begin: \@@_empty: \@@_save_parshape: \@@_parbox_restore: \vbox_set:Nw \l_@@_body_box \@@_set_prevdepth:N \g_@@_prevdepth_dim \@@_save_tex_skip: \@@_tex_parameter: \@@_restore_parshape: \@@_display_parameter: \@@_make_main_parshape: \para_raw_noindent: } { \@@_save_hangfrom: \@@_save_tex_skip: \@@_group_kludge: \@@_tex_parameter: \@@_make_main_parshape: \para_raw_end: \int_gset_eq:NN \g_@@_line_int \tex_prevgraf:D \vbox_set_end: \@@_adjust_tex_skip: \cs_gset_eq:NN \@@_para_end: \@@_empty: \cs_gset_eq:NN \@@_para_after: \@@_empty: \int_compare:nNnTF \g_@@_line_int > \l_@@_top_int { \@@_build_par: } { \@@_put_par: } } \box_new:N \l_@@_body_box \box_new:N \l_@@_window_box \int_new:N \l_@@_window_int \int_new:N \g_@@_line_int \int_new:N \l_@@_window_line_int \dim_new:N \l_@@_l_dim \dim_new:N \l_@@_r_dim \dim_new:N \l_@@_min_dim \dim_new:N \l_@@_line_dim \dim_new:N \l_@@_window_dim \dim_new:N \l_@@_display_dim \dim_new:N \l_@@_voffset_dim \dim_new:N \l_@@_leftsep_dim \dim_new:N \l_@@_rightsep_dim \dim_new:N \l_@@_main_width_dim \bool_new:N \l_@@_hang_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_hang_left:, \@@_set_hang_right:, \@@_set_window:,} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_hang_left: { \bool_set_true:N \l_@@_hang_bool \@@_set_hoffset:N \l_@@_rightsep_dim \dim_zero:N \l_@@_l_dim \dim_set_eq:NN \l_@@_r_dim \l_@@_window_dim \cs_set_eq:NN \@@_build_box: \@@_build_hang: } \cs_new_protected_nopar:Npn \@@_set_hang_right: { \bool_set_true:N \l_@@_hang_bool \@@_set_hoffset:N \l_@@_leftsep_dim \dim_zero:N \l_@@_r_dim \dim_set_eq:NN \l_@@_l_dim \l_@@_window_dim \cs_set_eq:NN \@@_build_box: \@@_build_hang: } \cs_new_protected_nopar:Npn \@@_set_window: { \bool_set_false:N \l_@@_hang_bool \dim_sub:Nn \l_@@_window_dim { \l_@@_leftsep_dim + \l_@@_rightsep_dim } \dim_set:Nn \l_@@_l_dim { \@@_ratio:Nn \l_@@_ratio_fp { \l_@@_window_dim } } \dim_set:Nn \l_@@_r_dim { \l_@@_window_dim - \l_@@_l_dim } \bool_if:NTF \l_@@_column_bool { \cs_set_eq:NN \@@_build_box: \@@_build_column: } { \cs_set_eq:NN \@@_build_box: \@@_build_block: } } % \end{macrocode} % \end{macro} % % \changes{v0.2}{2022/07/24}{修复 \opt{hoffset} 选项。} % % \begin{macro}{\@@_set_hoffset:N} % \begin{macrocode} \cs_new_protected:Npn \@@_set_hoffset:N #1 { \dim_sub:Nn \l_@@_window_dim {#1} \group_begin: \dim_set:Nn \l_@@_width_dim { #1 + \g_@@_stuff_wd_dim } \cs_set_eq:NN \width \l_@@_width_dim \exp_args:NNNx \group_end: \dim_add:Nn \l_@@_window_dim { \dim_eval:n { \l_@@_hoffset_tl } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_lines:, \@@_window_init:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_lines: { \bool_if:NTF \g_@@_next_bool { \tl_clear:N \l_@@_lines_tl } { \tl_set:Nx \l_@@_lines_tl { \l_@@_lines_tl } } \int_set:Nn \l_@@_window_int { \tl_if_empty:NTF \l_@@_lines_tl { \@@_unit:n { \g_@@_remaining_dim + \l_@@_min_dim } } { \l_@@_lines_tl } } \bool_if:NF \g_@@_next_bool { \@@_window_init: } \int_compare:nNnTF \g_@@_top_int < \c_zero_int { \int_compare:nNnT \l_@@_top_int < \c_zero_int { \int_zero:N \l_@@_top_int } } { \int_set_eq:NN \l_@@_top_int \g_@@_top_int } } \cs_new_protected_nopar:Npn \@@_window_init: { \int_gset_eq:NN \g_@@_column_int \l_@@_window_int \dim_gset:Nn \g_@@_window_ht_dim { \tex_baselineskip:D * \g_@@_column_int } \tl_if_empty:NF \l_@@_lines_tl { \dim_gset:Nn \g_@@_remaining_dim { \g_@@_window_ht_dim - \box_ht:N \strutbox } \dim_gset_eq:NN \g_@@_stuff_ht_dim \g_@@_remaining_dim } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_make_main_parshape:} % 主要处理用于标题悬挂的 \tn{@hangfrom} 和用于列表环境的 \tn{parshape}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_make_main_parshape: { \dim_compare:nNnTF \g_@@_hangindent_dim > \c_zero_dim { \int_compare:nNnTF \g_@@_hangafter_int = \c_one_int { \@@_make_hangfrom: } { \@@_make_main_parshape_aux: } } { \@@_make_main_parshape_aux: } } \cs_new_protected_nopar:Npn \@@_make_main_parshape_aux: { \bool_gset_false:N \g_@@_hangfrom_bool \tex_parshape:D \int_eval:n { \l_@@_top_int + 1 } ~ \prg_replicate:nn { \l_@@_top_int } { \g_@@_parshape_indent_dim \g_@@_parshape_length_dim } \c_zero_dim \c_max_dim } \cs_new_protected_nopar:Npn \@@_save_parshape: { \int_gset_eq:NN \g_@@_parshape_int \tex_parshape:D \int_compare:nNnTF \g_@@_parshape_int = \c_one_int { \dim_gset:Nn \g_@@_parshape_indent_dim { \tex_parshapeindent:D \c_one_int } \dim_gset:Nn \g_@@_parshape_length_dim { \tex_parshapelength:D \c_one_int } } { \int_gzero:N \g_@@_parshape_int \dim_gzero:N \g_@@_parshape_indent_dim \dim_gset_eq:NN \g_@@_parshape_length_dim \l_@@_main_width_dim \int_gset_eq:NN \g_@@_hangafter_int \tex_hangafter:D \dim_gset_eq:NN \g_@@_hangindent_dim \tex_hangindent:D } } \cs_new_protected_nopar:Npn \@@_restore_parshape: { \int_compare:nNnTF \g_@@_parshape_int = \c_one_int { \tex_parshape:D \g_@@_parshape_int \g_@@_parshape_indent_dim \g_@@_parshape_length_dim } { \@@_restore_hangfrom: } } \cs_new_protected_nopar:Npn \@@_parshape_kern: { \dim_compare:nNnT \l_@@_l_dim = \c_zero_dim { \dim_compare:nNnF \g_@@_parshape_indent_dim = \c_zero_dim { \tex_kern:D - \g_@@_parshape_indent_dim } } } \cs_new_protected_nopar:Npn \@@_make_hangfrom: { \bool_if:NTF \l_@@_hang_bool { \@@_make_hangfrom_aux: } { \@@_make_main_parshape_aux: } } \cs_new_protected_nopar:Npn \@@_make_hangfrom_aux: { \@@_restore_hangfrom: \int_zero:N \tex_parshape:D \bool_gset_true:N \g_@@_hangfrom_bool \dim_set_eq:NN \tex_hsize:D \l_@@_window_dim } \cs_new_protected_nopar:Npn \@@_save_hangfrom: { \int_gset_eq:NN \g_@@_hangafter_int \tex_hangafter:D \dim_gset_eq:NN \g_@@_hangindent_dim \tex_hangindent:D } \cs_new_protected_nopar:Npn \@@_restore_hangfrom: { \int_set_eq:NN \tex_hangafter:D \g_@@_hangafter_int \dim_set_eq:NN \tex_hangindent:D \g_@@_hangindent_dim } \bool_new:N \g_@@_hangfrom_bool \int_new:N \g_@@_parshape_int \int_new:N \g_@@_hangafter_int \dim_new:N \g_@@_hangindent_dim % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_group_kludge:} % \LaTeX\ 的 \tn{list} 环境中,为了保持 \tn{parshape},\tn{par} 被重定义为 |{\@@par}|。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_group_kludge: { \scan_stop: \int_compare:nNnTF \tex_currentgrouptype:D = \c_one_int { \c_group_end_token \cs_gset_eq:NN \@@_group_begin: \c_group_begin_token } { \cs_gset_eq:NN \@@_group_begin: \@@_empty: } \legacy_if:nTF { @noitemarg } { \cs_gset_eq:NN \@@_set_itemarg: \@noitemargtrue } { \cs_gset_eq:NN \@@_set_itemarg: \@@_empty: } } \cs_new_eq:NN \@@_set_itemarg: \@@_empty: \cs_new_eq:NN \@@_group_begin: \@@_empty: \@@_gadd_hook:nn { env/wrapstuff@par/after } { \@@_set_itemarg: \@@_group_begin: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ratio:Nn, \@@_unit:n} % \begin{macrocode} \cs_new:Npn \@@_ratio:Nn #1#2 { \fp_to_dim:n { #1 \dim_to_fp:n {#2} } } \cs_new:Npn \@@_unit:n #1 { \int_eval:n { \exp_last_unbraced:Ne \@@_unit_aux:w { \dim_to_decimal_in_unit:nn {#1} { \tex_baselineskip:D } } \s_stop } } \cs_new:Npn \@@_unit_aux:w #1 . #2 \s_stop { #1 + 1 } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_save_tex_skip:,\@@_tex_parameter:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_save_tex_skip: { \skip_gset_eq:NN \g_@@_left_skip \tex_leftskip:D \skip_gset_eq:NN \g_@@_right_skip \tex_rightskip:D \skip_gset_eq:NN \g_@@_parfill_skip \tex_parfillskip:D \skip_gset_eq:NN \g_@@_baseline_skip \tex_baselineskip:D \skip_gset:Nn \g_@@_main_left_skip { - \tex_leftskip:D } } \cs_new_protected_nopar:Npn \@@_adjust_tex_skip: { \@@_adjust_skip:N \g_@@_left_skip \@@_adjust_skip:N \g_@@_right_skip \@@_adjust_skip:N \g_@@_parfill_skip } \cs_new_protected:Npn \@@_adjust_skip:N #1 { \skip_gsub:Nn #1 { \dim_eval:n {#1} } } \cs_new_protected_nopar:Npn \@@_tex_parameter: { \int_zero:N \tex_clubpenalty:D \int_zero:N \tex_widowpenalty:D \int_zero:N \tex_interlinepenalty:D \int_zero:N \tex_displaywidowpenalty:D \int_zero:N \tex_clubpenalties:D \int_zero:N \tex_widowpenalties:D \int_zero:N \tex_interlinepenalties:D \int_zero:N \tex_displaywidowpenalties:D \skip_set_eq:NN \tex_leftskip:D \g_@@_left_skip \skip_set_eq:NN \tex_rightskip:D \g_@@_right_skip \skip_set_eq:NN \tex_parfillskip:D \g_@@_parfill_skip \skip_set_eq:NN \tex_baselineskip:D \g_@@_baseline_skip } \skip_new:N \g_@@_left_skip \skip_new:N \g_@@_right_skip \skip_new:N \g_@@_parfill_skip \skip_new:N \g_@@_baseline_skip \skip_new:N \g_@@_main_left_skip % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_display_parameter:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_display_parameter: { \bool_gset_false:N \g_@@_display_bool \tex_everydisplay:D \exp_after:wN { \tex_the:D \tex_everydisplay:D \@@_display_hook: } } \cs_new_protected_nopar:Npn \@@_display_hook: { \@@_test_leqno: \dim_compare:nNnF \tex_displaywidth:D < \c_max_dim { \bool_gset_true:N \g_@@_display_bool \dim_set_eq:NN \tex_displaywidth:D \l_@@_display_dim } } \cs_new_eq:NN \@@_test_leqno: \@@_empty: \cs_new_protected_nopar:Npn \@@_clear_display_hook: { \cs_gset_eq:NN \@@_display_hook: \@@_empty: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_split_parameter:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_split_parameter: { \skip_zero:N \tex_splittopskip:D \dim_set_eq:NN \tex_vfuzz:D \c_max_dim \int_set_eq:NN \tex_vbadness:D \c_max_int } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_par:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_par: { \bool_if:NTF \g_@@_hangfrom_bool { \@@_build_box: } { \@@_build_par_aux: } \box_if_empty:NTF \l_@@_window_box { \@@_put_next_par: } { \@@_put_box: } } \cs_new_protected_nopar:Npn \@@_build_par_aux: { \@@_extract_display_hbox:NN \l_@@_body_box \l_@@_bottom_box \int_compare:nNnT \l_@@_top_int > \c_zero_int { \@@_put_body_box: } \box_if_empty:NTF \l_@@_bottom_box { \box_if_empty:NF \g_@@_display_box { \@@_build_display_box: } } { \@@_build_body_box: } } \box_new:N \l_@@_bottom_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_put_par:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_put_par: { \int_gset:Nn \g_@@_top_int { \l_@@_top_int - \g_@@_line_int } \int_gzero:N \g_@@_window_int \@@_put_body_box: \skip_zero:N \tex_parskip:D \para_raw_noindent: \@@_next_para: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_put_body_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_put_body_box: { \@@_para_raw_end: \dim_compare:nNnTF { \box_wd:N \l_@@_body_box } < \c_max_dim { \@@_put_body_aux:N \l_@@_body_box } { \@@_extract_hbox:NN \l_@@_body_box \l_@@_bottom_box \@@_put_body_aux:N \l_@@_body_box \box_set_eq_drop:NN \l_@@_body_box \l_@@_bottom_box } \@@_para_raw_end: } \cs_new_protected_nopar:Npn \@@_put_body_aux:N #1 { \dim_gset:Nn \g_@@_prevdepth_dim { \box_dp:N #1 } \dim_compare:nNnT \g_@@_prevdepth_dim = \c_zero_dim { \@@_extract_depth:N #1 } \vbox_unpack_drop:N #1 \@@_set_prevdepth:N \g_@@_prevdepth_dim } \cs_new_protected_nopar:Npn \@@_extract_depth:N #1 { \vbox_set:Nn \l_@@_last_box { \vbox_unpack:N #1 \@@_if_last_hlist:F { \tex_unskip:D \tex_unpenalty:D \tex_unskip:D \tex_unpenalty:D } \@@_if_last_hlist:T { \box_set_to_last:N \l_@@_last_box \dim_gset:Nn \g_@@_prevdepth_dim { \box_dp:N \l_@@_last_box } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_put_next_par:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_put_next_par: { \int_gzero:N \g_@@_top_int \int_gzero:N \g_@@_window_int \skip_zero:N \tex_parskip:D \para_raw_noindent: \@@_next_para: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_display_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_display_box: { \bool_set_true:N \l_@@_display_bool \bool_if:NTF \g_@@_amsmath_bool { \@@_build_display_amsmath: } { \@@_build_display_normal: } \box_if_empty:NTF \l_@@_body_box { \@@_build_display_auxi: } { \@@_build_display_auxii: } } \cs_new_protected_nopar:Npn \@@_build_display_amsmath: { \group_begin: \vbox_gset:Nn \g_@@_equation_box { \@@_break: \vbox_unpack_drop:N \g_@@_display_box \skip_gset_eq:NN \g_@@_pos_skip \tex_lastskip:D \tex_unskip:D \int_gset_eq:NN \g_@@_pos_int \tex_lastpenalty:D \tex_unpenalty:D \skip_gadd:Nn \g_@@_pos_skip { \tex_lastskip:D } \tex_unskip:D \tex_unpenalty:D } \@@_split_parameter: \vbox_set_split_to_ht:NNn \l_@@_last_box \g_@@_equation_box { \c_zero_dim } \group_end: \box_gset_wd:Nn \g_@@_equation_box { \l_@@_display_dim } \vbox_gset:Nn \g_@@_display_box { \tex_penalty:D \g_@@_display_pre_int \skip_vertical:N \g_@@_display_pre_skip } \skip_gset_eq:NN \g_@@_pre_skip \g_@@_display_pre_skip } \cs_new_protected_nopar:Npn \@@_build_display_normal: { \vbox_gset:Nn \g_@@_display_box { \vbox_unpack_drop:N \g_@@_display_box \skip_gset_eq:NN \g_@@_pos_skip \tex_lastskip:D \tex_unskip:D \int_gset_eq:NN \g_@@_pos_int \tex_lastpenalty:D \tex_unpenalty:D \box_gset_to_last:N \g_@@_equation_box \skip_gset_eq:NN \g_@@_pre_skip \tex_lastskip:D \tex_unskip:D \skip_gadd:Nn \g_@@_pre_skip { \tex_lastskip:D } \tex_unskip:D \skip_vertical:N \g_@@_pre_skip } } \cs_new_protected_nopar:Npn \@@_build_display_auxi: { \bool_if:NTF \g_@@_amsmath_bool { \box_set_eq_drop:NN \l_@@_window_box \g_@@_equation_box } { \hbox_set_to_wd:Nnn \l_@@_window_box { \l_@@_display_dim } { \tex_hss:D \@@_adjust_equation: \box_use_drop:N \g_@@_equation_box \tex_hss:D } } \dim_gset:Nn \g_@@_ht_dim { \box_ht:N \l_@@_window_box } \dim_add:Nn \l_@@_voffset_dim { \box_ht:N \g_@@_display_box / 2 } } \cs_new_protected_nopar:Npn \@@_build_display_auxii: { \box_if_horizontal:NTF \l_@@_body_box { \box_set_eq:NN \l_@@_bottom_box \l_@@_body_box \@@_build_display_auxiii: } { \@@_extract_hbox:NN \l_@@_body_box \l_@@_bottom_box \str_if_eq:eeTF { \dim_eval:n { \box_ht:N \l_@@_body_box } \dim_eval:n { \box_dp:N \l_@@_body_box } \dim_eval:n { \box_ht:N \l_@@_bottom_box } \dim_eval:n { \box_dp:N \l_@@_bottom_box } } { \c_@@_zero_pt_str } { \vbox_unpack_drop:N \l_@@_body_box \box_clear:N \l_@@_bottom_box \@@_build_display_auxi: } { \@@_build_display_auxiii: } } } \str_const:Nx \c_@@_zero_pt_str { \dim_use:N \c_zero_dim \dim_use:N \c_zero_dim \dim_use:N \c_zero_dim \dim_use:N \c_zero_dim } \cs_new_protected_nopar:Npn \@@_build_display_auxiii: { \bool_set_true:N \l_@@_attach_equation_bool \box_gclear:N \g_@@_display_box \bool_if:NF \g_@@_amsmath_bool { \@@_adjust_equation: } \@@_build_body_box: } \bool_new:N \l_@@_display_bool \bool_new:N \l_@@_attach_equation_bool % \end{macrocode} % \end{macro} % % \changes{v0.2}{2022/07/23}{改进对显示数学公式的处理。} % % \begin{macro}{\@@_attach_left:N,\@@_attach_right:N} % \begin{macrocode} \cs_new_protected:Npn \@@_attach_left:N #1 { \@@_attach_equation:Nn #1 { \g_@@_parshape_indent_dim } } \cs_new_protected:Npn \@@_attach_right:N #1 { \@@_attach_equation:Nn #1 { \l_@@_line_dim - \l_@@_display_dim + \g_@@_parshape_indent_dim } } \cs_new_protected:Npn \@@_attach_equation:Nn #1#2 { \vbox_set:Nn \l_@@_last_box { \vbox_unpack:N #1 \box_set_to_last:N \l_@@_last_box \bool_if:NTF \g_@@_amsmath_bool { \@@_attach_equation_amsmath:Nn } { \@@_attach_equation_normal:Nn } \l_@@_last_box {#2} } } \cs_new_protected:Npn \@@_attach_equation_amsmath:Nn #1#2 { \vbox_gset:Nn \g_@@_equation_box { \@@_nobreak: \skip_vertical:n { \g_@@_display_pre_skip + \g_@@_display_pre_dim - \box_dp:N #1 } \box_move_right:nn {#2} { \box_use_drop:N \g_@@_equation_box } } } \cs_new_protected:Npn \@@_attach_equation_normal:Nn #1#2 { \vbox_set:Nn \l_@@_last_box { \@@_tex_parameter: \dim_set_eq:NN \tex_hsize:D \l_@@_display_dim \para_raw_noindent: \hbox_unpack_drop:N #1 \tex_unskip:D \@@_insert_equation: \para_raw_end: \skip_gset_eq:NN \g_@@_pos_skip \tex_lastskip:D \tex_unskip:D \int_gset_eq:NN \g_@@_pos_int \tex_lastpenalty:D \tex_unpenalty:D \box_set_to_last:N \l_@@_last_box \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \tex_unskip:D \skip_add:Nn \l_@@_last_skip { \tex_lastskip:D } \vbox_gset:Nn \g_@@_equation_box { \@@_nobreak: \skip_vertical:N \l_@@_last_skip \box_move_right:nn {#2} { \hbox_to_wd:nn { \l_@@_display_dim } { \tex_hss:D \box_use_drop:N \l_@@_last_box \tex_hss:D } } } } } \cs_new_protected_nopar:Npn \@@_insert_equation: { \c_math_toggle_token \c_math_toggle_token \dim_compare:nNnTF \tex_displaywidth:D = \l_@@_display_dim { \box_use_drop:N \g_@@_equation_box } { \bool_if:NTF \g_@@_eqnum_bool { \@@_repack_equation: } { \box_use_drop:N \g_@@_equation_box } } \c_math_toggle_token \c_math_toggle_token } \cs_new_protected_nopar:Npn \@@_repack_equation: { \box_gclear:N \g_@@_equation_box \box_use_drop:N \g_@@_eqbody_box \bool_if:NTF \g_@@_leqno_bool { \tex_leqno:D } { \tex_eqno:D } \box_use_drop:N \g_@@_eqnum_box } \cs_new_protected_nopar:Npn \@@_adjust_equation: { \@@_test_eqnum: \bool_if:NT \g_@@_eqnum_bool { \@@_adjust_equation_width: } } \cs_new_protected_nopar:Npn \@@_test_eqnum: { \hbox_set:Nn \l_@@_last_box { \bool_gset_false:N \g_@@_eqnum_bool \hbox_unpack:N \g_@@_equation_box \@@_if_last_hlist:F { \use_none_delimit_by_s_stop:w } \box_gset_to_last:N \g_@@_eqnum_box \@@_if_last_kern:F { \use_none_delimit_by_s_stop:w } \tex_unkern:D \@@_if_last_hlist:F { \use_none_delimit_by_s_stop:w } \box_gset_to_last:N \g_@@_eqbody_box \@@_if_last_none:F { \use_none_delimit_by_s_stop:w } \bool_gset_true:N \g_@@_eqnum_bool \use_none_delimit_by_s_stop:w \s_stop } } \cs_new_protected_nopar:Npn \@@_adjust_equation_width: { \bool_if:NTF \g_@@_leqno_bool { \@@_adjust_leqno: } { \box_gset_wd:Nn \g_@@_equation_box { \box_wd:N \g_@@_eqbody_box } } } \cs_new_protected_nopar:Npn \@@_adjust_leqno: { \box_set_eq_drop:NN \l_@@_last_box \g_@@_eqnum_box \box_gset_eq_drop:NN \g_@@_eqnum_box \g_@@_eqbody_box \box_gset_eq_drop:NN \g_@@_eqbody_box \l_@@_last_box \hbox_gset:Nn \g_@@_equation_box { \skip_horizontal:n { \box_wd:N \g_@@_eqbody_box - \box_wd:N \g_@@_equation_box } \box_use_drop:N \g_@@_equation_box } } \box_new:N \g_@@_eqbody_box \box_new:N \g_@@_eqnum_box \box_new:N \g_@@_equation_box \int_new:N \g_@@_pos_int \skip_new:N \g_@@_pos_skip \bool_new:N \g_@@_eqnum_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_pos_kludge:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_pos_kludge: { \dim_gset:Nn \g_@@_prevdepth_dim { \box_dp:N \l_@@_window_box } \bool_gset_false:N \g_@@_equation_dp_bool \bool_if:NTF \g_@@_next_bool { \tex_vadjust:D { \box_if_empty:NF \g_@@_equation_box { \@@_output_equation_box: } \@@_nobreak: \bool_if:NT \l_@@_display_bool { \skip_vertical:N \g_@@_pos_skip } } } { \bool_if:NT \l_@@_display_bool { \tex_vadjust:D { \box_if_empty:NF \g_@@_equation_box { \@@_output_equation_box: } \tex_penalty:D \g_@@_pos_int \skip_vertical:N \g_@@_pos_skip } } } \int_gzero:N \g_@@_pos_int \skip_gzero:N \g_@@_pos_skip } \cs_new_protected_nopar:Npn \@@_output_equation_box: { \cs_gset_eq:NN \@@_para_after: \@@_set_equation_depth: \bool_gset_true:N \g_@@_equation_dp_bool \dim_gset:Nn \g_@@_prevdepth_dim { \box_dp:N \g_@@_equation_box } \vbox_unpack_drop:N \g_@@_equation_box } \cs_new_protected_nopar:Npn \@@_set_equation_depth: { \cs_gset_eq:NN \@@_para_after: \@@_empty: \bool_gset_false:N \g_@@_equation_dp_bool \@@_set_prevdepth:N \g_@@_prevdepth_dim } \bool_new:N \g_@@_equation_dp_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_body_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_body_box: { \box_set_eq:NN \l_@@_save_body_box \l_@@_bottom_box \@@_build_window: \int_compare:nNnTF \g_@@_line_int > \l_@@_window_line_int { \@@_extract_hbox:NN \l_@@_body_box \l_@@_bottom_box } { \box_clear:N \l_@@_bottom_box } \box_if_empty:NF \l_@@_bottom_box { \bool_set_false:N \l_@@_attach_equation_bool } \box_clear:N \l_@@_window_box \@@_build_box: } \box_new:N \l_@@_save_body_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_body_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_window: { \vbox_set:Nn \l_@@_body_box { \dim_zero:N \tex_emergencystretch:D \dim_set_eq:NN \tex_hfuzz:D \c_max_dim \dim_set_eq:NN \tex_vfuzz:D \c_max_dim \int_set_eq:NN \tex_hbadness:D \c_max_int \int_set_eq:NN \tex_vbadness:D \c_max_int \int_set:Nn \tex_tolerance:D { 1000 } \para_raw_noindent: \hbox_unpack_drop:N \l_@@_bottom_box \@@_tex_parameter: \@@_make_parshape: \@@_interline_penalties: \para_raw_end: \int_gset_eq:NN \g_@@_line_int \tex_prevgraf:D } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_make_parshape:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_make_parshape: { \tex_parshape:D \int_eval:n { \l_@@_window_line_int + 1 } ~ \bool_if:NTF \l_@@_hang_bool { \prg_replicate:nn { \l_@@_window_int } { \c_zero_dim \l_@@_window_dim } } { \bool_if:NTF \l_@@_column_bool { \prg_replicate:nn { \l_@@_window_int / 2 } { \c_zero_dim \l_@@_l_dim } \prg_replicate:nn { \bool_if:NTF \g_@@_column_bool { \g_@@_column_int } { \l_@@_window_int / 2 } } { \c_zero_dim \l_@@_r_dim } } { \prg_replicate:nn { \l_@@_window_int / 2 } { \c_zero_dim \l_@@_l_dim \c_zero_dim \l_@@_r_dim } } } \c_zero_dim \c_max_dim } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_interline_penalties:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_interline_penalties: { \bool_if:NF \l_@@_hang_bool { \bool_if:NTF \l_@@_column_bool { \@@_column_penalties: } { \@@_block_penalties: } } } \cs_new_protected_nopar:Npn \@@_column_penalties: { \tex_interlinepenalties:D \int_eval:n { \l_@@_window_int / 2 + \c_one_int } ~ \prg_replicate:nn { \l_@@_window_int / 2 - \c_one_int } { \c_@@_nobreak_int } \c_@@_break_int \c_zero_int } \cs_new_protected_nopar:Npn \@@_block_penalties: { \tex_interlinepenalties:D \l_@@_window_int \prg_replicate:nn { \l_@@_window_int - \c_one_int } { \c_@@_break_int } \c_zero_int } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_break:,\@@_nobreak:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_break: { \tex_penalty:D \c_@@_break_int } \cs_new_protected_nopar:Npn \@@_nobreak: { \tex_penalty:D \c_@@_nobreak_int } \int_const:Nn \c_@@_break_int { -10000 } \int_const:Nn \c_@@_nobreak_int { 10000 } % \end{macrocode} % \end{macro} % % \changes{v0.2}{2022/07/22}{提高稳定性。} % % \begin{macro}{\@@_build_box:, \@@_build_block:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_block: { \vbox_set:Nn \l_@@_window_box { \@@_split_parameter: \skip_set_eq:NN \tex_baselineskip:D \g_@@_baseline_skip \@@_build_line: } } \cs_new_protected_nopar:Npn \@@_build_line: { \vbox_set_split_to_ht:NNn \l_@@_l_box \l_@@_body_box { \g_@@_baseline_skip } \vbox_set_split_to_ht:NNn \l_@@_r_box \l_@@_body_box { \g_@@_baseline_skip } \@@_build_line_repack: \box_if_empty:NTF \l_@@_body_box { \@@_put_last_line: } { \@@_put_line_box: \@@_build_line: } } \cs_new_protected_nopar:Npn \@@_build_line_repack: { \vbox_set:Nn \l_@@_l_box { \vbox_unpack_drop:N \l_@@_l_box } \box_if_empty:NF \l_@@_r_box { \vbox_set:Nn \l_@@_r_box { \vbox_unpack_drop:N \l_@@_r_box } } \@@_save_first_ht: } \cs_new_protected_nopar:Npn \@@_put_last_line: { \bool_if:NT \l_@@_attach_equation_bool { \@@_attach_left:N \l_@@_l_box } \@@_put_line_box: } \cs_new_protected_nopar:Npn \@@_put_line_box: { \hbox_to_wd:nn { \l_@@_line_dim } { \box_use_drop:N \l_@@_l_box \tex_hfil:D \box_use_drop:N \l_@@_r_box } } \cs_new_protected_nopar:Npn \@@_save_first_ht: { \dim_gset:Nn \g_@@_ht_dim { \dim_max:nn { \box_ht:N \l_@@_l_box } { \box_ht:N \l_@@_r_box } } \cs_set_eq:NN \@@_save_first_ht: \@@_empty: } \dim_new:N \g_@@_ht_dim \box_new:N \l_@@_l_box \box_new:N \l_@@_r_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_column_fuzzy:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_column_fuzzy: { \hbox_set_to_wd:Nnn \l_@@_window_box { \l_@@_line_dim } { \@@_split_parameter: \@@_build_column_aux: \box_if_empty:NT \l_@@_bottom_box { \@@_build_column_fuzzy_aux: } \@@_repack_left_box: \bool_if:NT \l_@@_attach_equation_bool { \@@_attach_left:N \l_@@_l_box } \box_use:N \l_@@_l_box \tex_hfil:D \box_move_up:nn { \box_ht:N \l_@@_l_box - \box_ht:N \l_@@_r_box } { \box_use_drop:N \l_@@_r_box } } } \cs_new_protected_nopar:Npn \@@_build_column_aux: { \vbox_set_split_to_ht:NNn \l_@@_l_box \l_@@_body_box { \box_ht:N \l_@@_body_box / 2 } \vbox_set_top:Nn \l_@@_l_box { \vbox_unpack_drop:N \l_@@_l_box } \box_set_eq_drop:NN \l_@@_r_box \l_@@_body_box } \cs_new_protected_nopar:Npn \@@_build_column_fuzzy_aux: { \dim_compare:nNnTF { \box_ht_plus_dp:N \l_@@_r_box - \box_ht_plus_dp:N \l_@@_l_box } > { \l_@@_min_dim } { \box_if_empty:NF \l_@@_last_l_box { \box_set_eq_drop:NN \l_@@_l_box \l_@@_last_l_box \box_set_eq_drop:NN \l_@@_r_box \l_@@_last_r_box } } { \@@_rebuild_window: } } \cs_new_protected_nopar:Npn \@@_rebuild_window: { \int_compare:nNnT \l_@@_window_int > { 2 } { \@@_rebuild_window_aux: } } \cs_new_protected_nopar:Npn \@@_rebuild_window_aux: { \int_sub:Nn \l_@@_window_int { 2 } \box_set_eq_drop:NN \l_@@_last_l_box \l_@@_l_box \box_set_eq_drop:NN \l_@@_last_r_box \l_@@_r_box \box_set_eq:NN \l_@@_bottom_box \l_@@_save_body_box \int_set_eq:NN \l_@@_window_line_int \l_@@_window_int \@@_build_window: \@@_build_column_aux: \@@_build_column_fuzzy_aux: } \box_new:N \l_@@_last_l_box \box_new:N \l_@@_last_r_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_column_strict:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_column_strict: { \group_begin: \@@_split_parameter: \@@_build_column_aux: \box_if_empty:NTF \l_@@_r_box { \@@_build_column_strict_auxi: } { \box_if_empty:NTF \l_@@_bottom_box { \@@_build_column_strict_auxii: } { \bool_if:NTF \g_@@_column_bool { \@@_build_column_strict_auxiii: } { \@@_build_column_strict_auxiv: } } } \group_end: \box_set_eq_drop:NN \l_@@_window_box \g_@@_window_box } \cs_new_protected_nopar:Npn \@@_build_column_strict_auxi: { \@@_repack_left_box: \bool_if:NT \l_@@_attach_equation_bool { \@@_attach_left:N \l_@@_l_box } \box_gset_eq_drop:NN \g_@@_window_box \l_@@_l_box \bool_gset_true:N \g_@@_column_bool \bool_if:NF \g_@@_first_save_bool { \bool_gset_true:N \g_@@_first_save_bool \dim_gset:Nn \g_@@_first_sep_dim { \tex_baselineskip:D - \g_@@_ht_dim } \dim_gset_eq:NN \g_@@_first_dp_dim \g_@@_prevdepth_dim } \int_case:nnT { \g_@@_window_int } { { \c_zero_int } { } { \g_@@_line_int } { } } { \@@_column_move_entire_aux: } } \cs_new_protected_nopar:Npn \@@_column_move_entire_aux: { \bool_gset_true:N \g_@@_entire_bool \bool_gset_true:N \g_@@_next_hang_bool } \cs_new_protected_nopar:Npn \@@_column_move_entire: { \dim_gsub:Nn \g_@@_first_sep_dim { \box_dp:N \l_@@_window_box } \bool_gset_false:N \g_@@_entire_bool \dim_gzero:N \g_@@_column_ht_dim \dim_gset_eq:NN \g_@@_prevdepth_dim \g_@@_first_dp_dim \@@_column_right_move_set:nn { \g_@@_stuff_ht_dim } { \g_@@_window_ht_dim } \int_gset_eq:NN \g_@@_window_int \g_@@_column_int } \cs_new_protected:Npn \@@_column_right_move_set:nn #1#2 { \bool_gset_true:N \g_@@_right_move_bool \bool_gset_true:N \g_@@_first_set_bool \tl_gput_right:Nn \g_@@_main_setting_tl { \bool_if:NTF \g_@@_first_set_bool { \bool_gset_false:N \g_@@_first_set_bool \bool_set_true:N \l_@@_first_move_bool } { \bool_set_false:N \l_@@_first_move_bool } \fp_zero:N \l_@@_ratio_fp } \@@_make_next_stuff:nn { \l_@@_line_dim - \l_@@_r_dim - \l_@@_rightsep_dim } {#1} \dim_gset:Nn \g_@@_column_room_dim {#2} \int_gzero:N \g_@@_top_int } \cs_new_protected_nopar:Npn \@@_build_column_strict_auxii: { \bool_gset_false:N \g_@@_entire_bool \@@_repack_left_box: \bool_if:NT \l_@@_attach_equation_bool { \@@_attach_right:N \l_@@_r_box } \dim_gset:Nn \g_@@_hang_ht_dim { \g_@@_stuff_ht_dim - \tex_baselineskip:D * \@@_unit:n { \box_ht_plus_dp:N \l_@@_r_box } - \box_ht_plus_dp:N \g_@@_equation_box - \g_@@_pos_skip } \dim_compare:nNnTF \g_@@_hang_ht_dim > \c_zero_dim { \@@_column_move_right: } { \@@_column_put_right: } \box_gset_ht:Nn \g_@@_window_box { \box_ht:N \l_@@_l_box } \box_gset_dp:Nn \g_@@_window_box { \box_dp:N \l_@@_l_box } } \cs_new_protected_nopar:Npn \@@_column_move_right: { \int_compare:nNnTF \g_@@_window_int > \c_zero_int { \dim_gset:Nn \g_@@_column_room_dim { \g_@@_window_ht_dim - \g_@@_first_sep_dim - \box_ht_plus_dp:N \l_@@_r_box - \box_ht_plus_dp:N \g_@@_equation_box } \@@_next_hang_para: } { \dim_gset:Nn \g_@@_column_room_dim { \box_ht:N \l_@@_l_box - \box_ht_plus_dp:N \l_@@_r_box - \box_ht_plus_dp:N \g_@@_equation_box } \dim_gset:Nn \g_@@_first_sep_dim { \tex_baselineskip:D - \g_@@_ht_dim } \bool_gset_true:N \g_@@_right_move_bool \bool_gset_true:N \g_@@_next_hang_bool } \hbox_gset_to_wd:Nnn \g_@@_window_box { \l_@@_line_dim } { \box_use:N \l_@@_l_box \tex_hfil:D \box_move_up:nn { \g_@@_column_room_dim } { \box_use:N \l_@@_r_box } } \dim_gset:Nn \g_@@_column_ht_dim { \box_ht_plus_dp:N \l_@@_r_box + \box_ht_plus_dp:N \g_@@_equation_box + \g_@@_pos_skip } } \cs_new_protected_nopar:Npn \@@_column_put_right: { \hbox_gset_to_wd:Nnn \g_@@_window_box { \l_@@_line_dim } { \box_use:N \l_@@_l_box \tex_hfil:D \box_move_up:nn { \int_compare:nNnTF \g_@@_window_int > \c_zero_int { \g_@@_window_ht_dim - \g_@@_first_sep_dim } { \box_ht:N \l_@@_l_box } - \box_ht:N \l_@@_r_box } { \box_use:N \l_@@_r_box } } \skip_gzero:N \g_@@_pos_skip } \cs_new_protected_nopar:Npn \@@_next_hang_para: { \bool_if:NTF \g_@@_entire_bool { \@@_column_move_entire: } { \@@_column_right_move_set:nn { \g_@@_hang_ht_dim } { \g_@@_column_room_dim } \int_gzero:N \g_@@_window_int } \bool_gset_false:N \g_@@_next_hang_bool } \cs_new_protected_nopar:Npn \@@_build_column_strict_auxiii: { \bool_gset_false:N \g_@@_column_bool \@@_repack_left_box: \hbox_gset_to_wd:Nnn \g_@@_window_box { \l_@@_line_dim } { \box_use:N \l_@@_l_box \tex_hfil:D \box_use:N \l_@@_r_box } \box_gset_ht:Nn \g_@@_window_box { \box_ht:N \l_@@_l_box } } \cs_new_protected_nopar:Npn \@@_build_column_strict_auxiv: { \@@_repack_left_box: \hbox_gset_to_wd:Nnn \g_@@_window_box { \l_@@_line_dim } { \box_use:N \l_@@_l_box \tex_hfil:D \box_move_up:nn { \box_ht:N \l_@@_l_box - \box_ht:N \l_@@_r_box } { \box_use_drop:N \l_@@_r_box } } } \cs_new_protected_nopar:Npn \@@_repack_left_box: { \dim_gset:Nn \g_@@_ht_dim { \box_ht:N \l_@@_l_box } \vbox_set:Nn \l_@@_l_box { \vbox_unpack_drop:N \l_@@_l_box } } \box_new:N \g_@@_window_box \bool_new:N \l_@@_first_move_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_box:,\@@_build_column:} % \begin{macrocode} \bool_new:N \l_@@_column_bool \cs_new_eq:NN \@@_build_column: \@@_build_column_strict: \cs_new_eq:NN \@@_build_box: \@@_build_column: % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_hang:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_hang: { \bool_if:NTF \g_@@_hangfrom_bool { \@@_build_hangfrom: } { \vbox_set_top:Nn \l_@@_window_box { \vbox_unpack:N \l_@@_body_box } \dim_gset:Nn \g_@@_ht_dim { \box_ht:N \l_@@_window_box } } \box_set_eq_drop:NN \l_@@_window_box \l_@@_body_box \bool_if:NT \l_@@_attach_equation_bool { \@@_build_hang_attach: } \dim_compare:nNnT \g_@@_column_room_dim > \c_zero_dim { \@@_build_hang_move: } } \cs_new_protected_nopar:Npn \@@_build_hang_attach: { \dim_compare:nNnTF \l_@@_r_dim = \c_zero_dim { \@@_attach_left:N \l_@@_window_box } { \@@_attach_right:N \l_@@_window_box } } \cs_new_protected_nopar:Npn \@@_build_hang_move: { \dim_set:Nn \l_@@_shift_dim { \dim_max:nn { \box_ht:N \l_@@_window_box } { \tex_baselineskip:D * \g_@@_line_int } + \box_ht_plus_dp:N \g_@@_equation_box + \tex_parskip:D } \dim_gsub:Nn \g_@@_column_room_dim { \l_@@_shift_dim } \dim_compare:nNnTF \g_@@_column_room_dim > \c_zero_dim { \box_if_empty:NTF \l_@@_bottom_box { \bool_if:NT \g_@@_right_move_bool { \@@_set_next_hang: } } } { \use:n } { \bool_gset_false:N \g_@@_move_hang_bool \bool_gset_false:N \g_@@_right_move_bool } } \cs_new_protected_nopar:Npn \@@_set_next_hang: { \bool_if:NF \g_@@_move_hang_bool { \bool_gset_true:N \g_@@_move_hang_bool \dim_gset_eq:NN \g_@@_hang_ht_dim \g_@@_remaining_dim } \dim_gsub:Nn \g_@@_hang_ht_dim { \l_@@_shift_dim } \@@_column_right_move_set:nn { \g_@@_hang_ht_dim } { \g_@@_column_room_dim } \int_gzero:N \g_@@_window_int } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_build_hangfrom:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_build_hangfrom: { \group_begin: \vbox_gset:Nn \g_@@_window_box { \@@_break: \vbox_unpack:N \l_@@_body_box } \@@_split_parameter: \vbox_set_split_to_ht:NNn \l_@@_last_box \g_@@_window_box { \c_zero_dim } \dim_gset:Nn \g_@@_ht_dim { \g_@@_baseline_skip - \g_@@_prevdepth_dim - \box_ht:N \l_@@_body_box + \box_ht:N \g_@@_window_box } \group_end: \box_set_eq_drop:NN \l_@@_body_box \g_@@_window_box } % \end{macrocode} % \end{macro} % % \changes{v0.3}{2022/07/31}{修复 stuff 深度不为零时的垂直对齐问题。} % % \begin{macro}{\@@_put_box:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_put_box: { \@@_para_raw_end: \dim_compare:nNnTF \g_@@_prevdepth_dim > \c_@@_ignore_depth_dim { \@@_add_vskip: } { \@@_set_vskip: } \skip_set_eq:NN \l_@@_par_skip \tex_parskip:D \skip_zero:N \tex_parskip:D \dim_set:Nn \l_@@_window_ht_dim { \box_ht_plus_dp:N \l_@@_window_box } \bool_if:NTF \g_@@_right_move_bool { \@@_put_box_aux: } { \box_if_empty:NTF \l_@@_bottom_box { \@@_put_next_test: } { \@@_put_box_aux: } } } \dim_new:N \l_@@_window_ht_dim \skip_new:N \l_@@_par_skip \cs_new_protected_nopar:Npn \@@_put_next_test: { \box_if_empty:NF \g_@@_equation_box { \dim_add:Nn \l_@@_window_ht_dim { \box_ht_plus_dp:N \g_@@_equation_box + \g_@@_pos_skip } } \dim_compare:nNnTF { \g_@@_remaining_dim + \g_@@_pos_skip } > \l_@@_window_ht_dim { \@@_set_next: } { \@@_put_box_aux: } } \cs_new_protected_nopar:Npn \@@_put_box_aux: { \@@_output_window_box: \box_if_empty:NTF \l_@@_bottom_box { \@@_put_trailer_box: } { \@@_put_bottom_box: } } \cs_new_protected_nopar:Npn \@@_put_trailer_box: { \bool_if:NTF \g_@@_next_hang_bool { \@@_next_hang_para: \@@_next_para_trailer: } { \bool_if:NTF \g_@@_right_move_bool { \@@_next_para_trailer: } { \@@_add_pos_kludge: \@@_put_pos_box: \@@_clear_variable: } } } \cs_new_protected_nopar:Npn \@@_put_bottom_box: { \@@_para_raw_end: \para_raw_noindent: \hbox_unpack_drop:N \l_@@_bottom_box \box_if_empty:NF \g_@@_equation_box { \@@_insert_equation: } \@@_put_pos_box: \@@_clear_variable: } \cs_new_protected_nopar:Npn \@@_output_window_box: { \@@_hbox:n { \@@_put_window_box: \bool_if:NF \g_@@_next_bool { \@@_output_stuff_box: } } } \cs_new_protected_nopar:Npn \@@_put_pos_box: { \box_if_empty:NF \g_@@_pos_box { \@@_output_pos_box: } } \cs_new_protected_nopar:Npn \@@_output_pos_box: { \@@_if_last_none:F { \@@_output_pos_box_aux: } \hbox_unpack_drop:N \g_@@_pos_box } \cs_new_protected_nopar:Npn \@@_output_pos_box_aux: { \@@_para_raw_end: \bool_if:NT \g_@@_equation_dp_bool { \@@_set_equation_depth: } \para_raw_noindent: } \cs_new_protected:Npn \@@_hbox:n #1 { \para_raw_noindent: \hbox_gset:Nn \g_@@_last_box {#1} \box_gset_wd:Nn \g_@@_last_box { \l_@@_line_dim } \box_use_drop:N \g_@@_last_box } \cs_new_protected_nopar:Npn \@@_put_window_box: { \dim_compare:nNnF \l_@@_l_dim > \c_zero_dim { \skip_horizontal:n { \l_@@_line_dim - \l_@@_r_dim } } \box_use:N \l_@@_window_box } \cs_new_protected_nopar:Npn \@@_output_stuff_box: { \hbox_gset:Nn \g_@@_stuff_box { \@@_parshape_kern: \box_move_up:nn { \box_dp:N \g_@@_stuff_box + \box_ht:N \l_@@_window_box - ( \l_@@_window_ht_dim + \box_ht_plus_dp:N \g_@@_stuff_box ) / 2 + \l_@@_voffset_dim } { \box_use_drop:N \g_@@_stuff_box } } \box_gset_ht:Nn \g_@@_stuff_box { \c_zero_dim } \box_gset_dp:Nn \g_@@_stuff_box { \c_zero_dim } \skip_horizontal:n { \dim_compare:nNnTF \l_@@_r_dim > \c_zero_dim { \dim_compare:nNnTF { \box_wd:N \l_@@_window_box } < { \l_@@_window_dim } { \l_@@_leftsep_dim } { - \l_@@_r_dim - \l_@@_rightsep_dim - \g_@@_stuff_wd_dim } } { \l_@@_leftsep_dim } } \box_use_drop:N \g_@@_stuff_box } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_vskip:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_vskip: { \box_if_empty:NTF \g_@@_display_box { \@@_add_vskip_auxi: } { \@@_add_vskip_display: } } \cs_new_protected_nopar:Npn \@@_add_vskip_display: { \bool_set_true:N \l_@@_display_pre_bool \vbox_unpack_drop:N \g_@@_display_box \@@_ignore_depth: } \cs_new_protected_nopar:Npn \@@_add_vskip_auxi: { \dim_compare:nNnTF \tex_pagegoal:D < \c_max_dim { \@@_add_vskip_auxii: } { \bool_if:NTF \g_@@_next_bool { \@@_add_vskip_auxii: } { \@@_add_vskip_auxiii: } } } \cs_new_protected_nopar:Npn \@@_add_vskip_auxii: { \@@_add_vskip_auxiv: \bool_if:NTF \l_@@_first_move_bool { \@@_first_move_skip: } { \skip_vertical:N \g_@@_pre_skip } \@@_ignore_depth: } \cs_new_protected_nopar:Npn \@@_add_vskip_auxiii: { \@@_add_vskip_auxiv: \skip_vertical:N \g_@@_pre_skip \dim_compare:nNnTF \tex_topskip:D > \g_@@_ht_dim { \skip_sub:Nn \tex_topskip:D { \g_@@_ht_dim } \tex_hrule:D height \c_zero_dim \scan_stop: } { \@@_ignore_depth: } } \cs_new_protected_nopar:Npn \@@_add_vskip_auxiv: { \skip_gset:Nn \g_@@_pre_skip { \g_@@_baseline_skip - \g_@@_prevdepth_dim - \g_@@_ht_dim } \dim_compare:nNnT \g_@@_pre_skip < \tex_lineskiplimit:D { \skip_gset_eq:NN \g_@@_pre_skip \tex_lineskip:D } } \cs_new_protected_nopar:Npn \@@_first_move_skip: { \skip_vertical:n { \g_@@_first_sep_dim - \g_@@_window_ht_dim - \tex_parskip:D \dim_compare:nNnT \g_@@_column_ht_dim > \c_zero_dim { + \g_@@_column_ht_dim + \g_@@_pre_skip } } } \skip_new:N \g_@@_pre_skip \bool_new:N \l_@@_display_pre_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_vskip:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_vskip: { \box_if_empty:NTF \g_@@_display_box { \skip_gset:Nn \g_@@_pre_skip { \g_@@_baseline_skip - \g_@@_ht_dim } } { \@@_add_vskip_display: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_ignore_depth:,\@@_set_prevdepth:N} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_ignore_depth: { \dim_set_eq:NN \tex_prevdepth:D \c_@@_ignore_depth_dim } \cs_new_protected_nopar:Npn \@@_set_prevdepth:N { \dim_set_eq:NN \tex_prevdepth:D } \dim_const:Nn \c_@@_ignore_depth_dim { -1000pt } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_set_next:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_next: { \dim_set:Nn \l_@@_height_dim { \bool_if:NT \g_@@_next_bool { \l_@@_par_skip } + \g_@@_pre_skip + \l_@@_window_ht_dim } \dim_gadd:Nn \g_@@_total_ht_dim { \l_@@_height_dim } \dim_set:Nn \l_@@_shift_dim { \g_@@_remaining_dim - \l_@@_height_dim } \dim_compare:nNnTF { - \l_@@_shift_dim } < \l_@@_min_dim { \@@_set_next_para: } { \@@_set_next_output: } } \cs_new_protected_nopar:Npn \@@_set_next_para: { \int_gset:Nn \g_@@_window_int { \dim_compare:nNnTF \l_@@_shift_dim > \c_zero_dim { \@@_unit:n { \l_@@_shift_dim } } { \c_one_int } } \@@_set_next_verify: \@@_output_window_box: \@@_make_next_stuff:nn { \g_@@_stuff_wd_dim } { \l_@@_shift_dim } \int_gzero:N \g_@@_top_int \@@_next_para_trailer: } \cs_new_protected_nopar:Npn \@@_set_next_output: { \@@_output_window_box: \@@_add_pos_kludge: \@@_put_pos_box: \@@_clear_variable: } \cs_new_protected_nopar:Npn \@@_set_next_verify: { \dim_set:Nn \l_@@_height_dim { \g_@@_window_ht_dim - \g_@@_total_ht_dim - \l_@@_min_dim } \dim_while_do:nNnn { \tex_baselineskip:D * \g_@@_window_int + \l_@@_par_skip } < { \l_@@_height_dim } { \int_gincr:N \g_@@_window_int } \bool_if:NF \g_@@_next_bool { \dim_add:Nn \l_@@_window_ht_dim { \tex_baselineskip:D * \g_@@_window_int + \l_@@_par_skip } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_next_para_trailer:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_next_para_trailer: { \@@_add_pos_kludge: \box_if_empty:NTF \g_@@_pos_box { \@@_next_para: } { \@@_env_begin: \hbox_unpack_drop:N \g_@@_pos_box \@@_env_end: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_make_next_stuff:nn} % \begin{macrocode} \cs_new_protected:Npn \@@_make_next_stuff:nn #1#2 { \bool_gset_true:N \g_@@_next_bool \dim_gset:Nn \g_@@_stuff_wd_dim {#1} \dim_gset:Nn \g_@@_remaining_dim {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_extract_hbox:NN} % \begin{macrocode} \cs_new_protected:Npn \@@_extract_display_hbox:NN #1 { \box_gclear:N \g_@@_pos_box \vbox_set:Nn #1 { \vbox_unpack_drop:N #1 \bool_if:NTF \g_@@_display_bool { \@@_test_display_math: } { \box_gclear:N \g_@@_display_box } \box_if_empty:NTF \g_@@_display_box { \bool_gset_false:N \g_@@_amsmath_bool \@@_extract_last_hbox:N \g_@@_last_box } { \box_gclear:N \g_@@_last_box } } \box_if_empty:NF \g_@@_display_box { \dim_gset:Nn \g_@@_display_pre_dim { \box_dp:N #1 } } \@@_extract_hbox_aux:N } \cs_new_protected:Npn \@@_extract_hbox:NN #1 { \vbox_set:Nn #1 { \vbox_unpack_drop:N #1 \@@_extract_last_hbox:N \g_@@_last_box } \@@_extract_hbox_aux:N } \cs_new_protected:Npn \@@_extract_hbox_aux:N #1 { \box_if_empty:NTF \g_@@_last_box { \box_clear:N #1 } { \@@_repack_hbox:N #1 } } \cs_new_protected:Npn \@@_repack_hbox:N #1 { \hbox_set:Nn #1 { \skip_if_eq:nnF { \g_@@_main_left_skip } { \c_zero_skip } { \skip_horizontal:N \g_@@_main_left_skip } \hbox_unpack_drop:N \g_@@_last_box \tex_unskip:D \tex_unskip:D \tex_unpenalty:D } } \cs_new_protected:Npn \@@_extract_last_hbox:N #1 { \@@_if_last_hlist:TF { \box_gset_to_last:N #1 \tex_unskip:D } { \box_gclear:N #1 } } \box_new:N \g_@@_last_box \box_new:N \g_@@_display_box \dim_new:N \g_@@_display_pre_dim % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_test_display_math:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_test_display_math: { \@@_if_last_hlist:T { \@@_extract_pos_hbox: } \box_clear:N \l_@@_add_box \box_gclear:N \g_@@_display_box \skip_gzero:N \g_@@_last_skip \skip_gzero:N \g_@@_display_pre_skip \bool_gset_false:N \g_@@_amsmath_bool \@@_add_last_skip:w \@@_add_last_penalty:w \@@_add_last_box:w \@@_add_last_skip:w \@@_add_last_skip:w \@@_add_last_penalty:w \@@_add_last_finalise:w \s_stop } \cs_new_protected_nopar:Npn \@@_extract_pos_hbox: { \box_gset_to_last:N \g_@@_last_box \@@_repack_hbox:N \l_@@_last_box \box_gset_eq_drop:NN \g_@@_pos_box \l_@@_last_box \tex_unskip:D } \box_new:N \l_@@_add_box \box_new:N \g_@@_pos_box % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_last_stop:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_last_stop:w { \vbox_unpack_drop:N \l_@@_add_box \use_none_delimit_by_s_stop:w } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_last_skip:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_last_skip:w { \@@_if_last_glue:TF { \skip_set_eq:NN \l_@@_last_skip \tex_lastskip:D \vbox_set:Nn \l_@@_add_box { \skip_vertical:N \l_@@_last_skip \vbox_unpack_drop:N \l_@@_add_box } \tex_unskip:D \skip_gadd:Nn \g_@@_last_skip { \l_@@_last_skip } } { \@@_skip_stop:w } } \skip_new:N \l_@@_last_skip \skip_new:N \g_@@_last_skip \cs_new_eq:NN \@@_skip_stop:w \@@_add_last_stop:w % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_last_penalty:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_last_penalty:w { \@@_if_last_penalty:TF { \int_set_eq:NN \l_@@_last_int \tex_lastpenalty:D \vbox_set:Nn \l_@@_add_box { \tex_penalty:D \l_@@_last_int \vbox_unpack_drop:N \l_@@_add_box } \tex_unpenalty:D \skip_gset_eq:NN \g_@@_pre_skip \g_@@_last_skip \skip_gzero:N \g_@@_last_skip } { \@@_penalty_stop:w } } \int_new:N \l_@@_last_int \cs_new_eq:NN \@@_penalty_stop:w \@@_add_last_stop:w % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_last_box:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_last_box:w { \@@_if_last_hlist:TF { \skip_gzero:N \g_@@_last_skip \box_set_to_last:N \l_@@_last_box \vbox_set:Nn \l_@@_add_box { \box_use_drop:N \l_@@_last_box \vbox_unpack_drop:N \l_@@_add_box } } { \@@_box_stop:w } } \box_new:N \l_@@_last_box \cs_new_eq:NN \@@_box_stop:w \@@_add_last_stop:w % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_add_last_finalise:w} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_add_last_finalise:w { \int_gset_eq:NN \g_@@_display_pre_int \l_@@_last_int \skip_gadd:Nn \g_@@_display_pre_skip { \g_@@_pre_skip } \int_case:nnTF { \tex_lastnodetype:D } { { \c_@@_hlist_node } { } { \c_@@_none_node } { } { \c_@@_whatsit_node } { } } { \box_gset_eq_drop:NN \g_@@_display_box \l_@@_add_box } { \vbox_unpack_drop:N \l_@@_add_box } \use_none_delimit_by_s_stop:w } \int_new:N \g_@@_display_pre_int \skip_new:N \g_@@_display_pre_skip % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_amsmath_boot:w,\@@_amsmath_recursion:w,\@@_amsmath_multline:w} % \pkg{amsmath} 的 \env{align} 等数学环境内部是一个 \tn{halign} 环境,结构不一样,需要另外处理。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_amsmath_boot:w { \@@_add_last_skip:w \@@_add_last_penalty:w \cs_set_eq:NN \@@_box_stop:w \@@_add_last_stop:w \@@_add_last_box:w \bool_gset_true:N \g_@@_amsmath_bool \cs_set_eq:NN \@@_skip_stop:w \@@_amsmath_multline:w \cs_set_eq:NN \@@_penalty_stop:w \@@_amsmath_stop:NN \@@_amsmath_recursion:w } \cs_new_protected_nopar:Npn \@@_amsmath_recursion:w { \@@_add_last_skip:w \@@_add_last_skip:w \@@_add_last_penalty:w \@@_add_last_box:w \@@_amsmath_recursion:w } \cs_new_protected:Npn \@@_amsmath_stop:NN #1#2 { \cs_set_eq:NN \@@_skip_stop:w \@@_add_last_stop:w \cs_set_eq:NN \@@_penalty_stop:w \@@_add_last_stop:w } \bool_new:N \g_@@_amsmath_bool % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_amsmath_multline:w} % \env{multline} 环境的结构与其他环境不一样。\pkg{amsmath} 的 \tn{@display@init} 定义为 % \begin{verbatim} % \def\@display@init#1{% % \global\dt@ptrue \spread@equation % \everycr{% % \noalign{% % #1% % \ifdt@p % \global\dt@pfalse % \vskip-\lineskiplimit % \vskip\normallineskiplimit % \else % \penalty\@eqpen \global\dspbrk@lvl\m@ne % \fi % }% % }% % } % \end{verbatim} % \env{align} 等环境的开头 \tn{ifdt@p} 为真,会插入两个 \tn{vskip}, % 但是 \env{multline} 定义中的 \tn{mmeasure@} 没有重定义 \tn{everycr}, % 上述定义中的 \tn{dt@pfalse} 被执行,导致环境开头被加入了 \tn{penalty}, % 不确定是有意为之还是疏忽^^A % \footnote{\url{https://github.com/latex3/latex2e/issues/793}}。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_amsmath_multline:w { \@@_amsmath_stop:NN ? ? \@@_add_last_penalty:w \skip_gset_eq:NN \g_@@_display_pre_skip \g_@@_pre_skip \@@_add_last_skip:w \@@_add_last_penalty:w \@@_add_last_finalise:w } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_amsmath_leqno:} % \pkg{amsmath} 的 \opt{leqno} 是直接用 \cs{tex_leqno:D} 实现的,与 \LaTeX\ 的实现不一样。 % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_amsmath_leqno: { \legacy_if:nTF { tagsleft@ } { \bool_gset_true:N \g_@@_leqno_bool } { \bool_gset_false:N \g_@@_leqno_bool } } % \end{macrocode} % \end{macro} % % \begin{macrocode} \@@_package_hook:nn { amsmath } { \cs_gset_eq:NN \@@_box_stop:w \@@_amsmath_boot:w \cs_gset_eq:NN \@@_test_leqno: \@@_amsmath_leqno: } % \end{macrocode} % % \begin{macro}{\@@_set_float:} % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_set_float: { \cs_set_eq:NN \@captype \l_@@_type_tl \@@_float_pre_hook: \@@_caption_hook: \@floatboxreset } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_float_pre_hook:, \@@_float_pos_hook:} % \begin{macrocode} \cs_new_eq:NN \@@_float_pre_hook: \@@_empty: \cs_new_eq:NN \@@_float_pos_hook: \@@_empty: \@@_package_hook:nn { float } { \bool_new:N \g_@@_float_pos_bool \cs_gset_protected_nopar:Npn \@@_float_pre_hook: { \exp_args:No \@@_float_pre_aux:n { \l_@@_type_tl } } \cs_new_protected:Npn \@@_float_pre_aux:n #1 { \cs_if_exist_use:cTF { fst@ #1 } { \@float@setevery {#1} \bool_gset_true:N \g_@@_float_pos_bool } { \bool_gset_false:N \g_@@_float_pos_bool } } \cs_gset_protected_nopar:Npn \@@_float_pos_hook: { \bool_if:NT \g_@@_float_pos_bool { \exp_args:No \@@_float_pos_aux:n { \l_@@_type_tl } } } \cs_new_protected:Npn \@@_float_pos_aux:n #1 { \hbox_gset:Nn \g_@@_stuff_box { \use:c { fst@ #1 } \cs_set_eq:NN \@currbox \g_@@_stuff_box \vbox_gset:Nn \g_@@_stuff_box { \box_use_drop:N \g_@@_stuff_box } \exp_args:Ne \float@makebox { \dim_eval:n { \box_wd:N \g_@@_stuff_box } } } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_floatrow_hook:} % \begin{macrocode} \cs_new_eq:NN \@@_floatrow_hook: \@@_empty: \@@_package_hook:nn { floatrow } { \cs_gset_protected_nopar:Npn \@@_floatrow_hook: { \cs_set_eq:NN \@captype \l_@@_type_tl \killfloatstyle \FR@redefs \dim_zero:N \FBc@wd \exp_args:Ne \flrow@setlist { { \l_@@_type_tl } { wrapfloat } { wrap \l_@@_type_tl } } \FRifFBOX \@@@@setframe \relax \@@@@FStrue \hbox_gset:Nw \g_@@_stuff_box \tl_set:Nx \FBB@wd { \dim_use:N \l_@@_width_dim } \FB@fs@wd \dim_set:Nn \l_@@_width_dim { \FBo@wd } } \cs_gset_protected_nopar:Npn \@@_float_pre_hook: { \the \FR@everyfloat } \cs_gset_protected_nopar:Npn \@@_float_pos_hook: { \legacy_if:nTF { FBbuild } { \cs_set_eq:NN \@currbox \g_@@_stuff_box \vbox_gset:Nn \g_@@_stuff_box { \box_use_drop:N \g_@@_stuff_box } \flrow@FB { \l_@@_width_dim } } { \cs_undefine:N \flrow@typ@tmpset \box_use_drop:N \g_@@_stuff_box } \hbox_gset_end: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_caption_hook:} % \begin{macrocode} \cs_new_eq:NN \@@_caption_hook: \@@_empty: \@@_package_hook:nn { caption } { \cs_gset_protected_nopar:Npn \@@_caption_hook: { \exp_args:No \@@_caption_aux:n { \l_@@_type_tl } } \cs_new_protected:Npn \@@_caption_aux:n #1 { \caption@settype {#1} \caption@clearmargin \caption@setoptions { wrap #1 } } } % \end{macrocode} % \end{macro} % % \begin{macro}{top} % \begin{macrocode} \keys_define:nn { wrapstuff } { abovesep .tl_set:N = \l_@@_abovesep_tl , belowsep .tl_set:N = \l_@@_belowsep_tl , leftsep .tl_set:N = \l_@@_leftsep_tl , rightsep .tl_set:N = \l_@@_rightsep_tl , linewidth .tl_set:N = \l_@@_linewidth_tl , lines .tl_set:N = \l_@@_lines_tl , width .tl_set:N = \l_@@_width_tl , height .tl_set:N = \l_@@_height_tl , hoffset .tl_set:N = \l_@@_hoffset_tl , voffset .tl_set:N = \l_@@_voffset_tl , type .tl_set:N = \l_@@_type_tl , ratio .fp_set:N = \l_@@_ratio_fp , top .int_set:N = \l_@@_top_int , i .code:n = \@@_swap_true:N \c_true_bool , o .code:n = \@@_swap_true:N \c_false_bool , l .code:n = \@@_swap_false:N \c_zero_fp , r .code:n = \@@_swap_false:N \c_one_fp , c .code:n = \@@_swap_false:N \c_@@_c_fp , column .choice: , column/true .code:n = { \bool_set_true:N \l_@@_column_bool \cs_set_eq:NN \@@_build_column: \@@_build_column_strict: } , column/par .code:n = { \bool_set_true:N \l_@@_column_bool \cs_set_eq:NN \@@_build_column: \@@_build_column_fuzzy: } , column/false .code:n = { \bool_set_false:N \l_@@_column_bool } , hsep .code:n = { \tl_set:Nn \l_@@_leftsep_tl {#1} \tl_set_eq:NN \l_@@_rightsep_tl \l_@@_leftsep_tl } , vsep .code:n = { \tl_set:Nn \l_@@_abovesep_tl {#1} \tl_set_eq:NN \l_@@_belowsep_tl \l_@@_abovesep_tl } , unknown .code:n = { \exp_args:No \@@_unknown_key:n { \l_keys_key_str } } , leftsep .groups:n = main , rightsep .groups:n = main , hsep .groups:n = main , linewidth .groups:n = main , lines .groups:n = main , column .groups:n = main , hoffset .groups:n = main , voffset .groups:n = main , top .groups:n = stuff , abovesep .groups:n = stuff , belowsep .groups:n = stuff , vsep .groups:n = stuff , width .groups:n = stuff , height .groups:n = stuff , float .groups:n = stuff , ratio .groups:n = ratio , l .groups:n = ratio , r .groups:n = ratio , c .groups:n = ratio , i .groups:n = ratio , o .groups:n = ratio , column .default:n = true , column .initial:n = true , abovesep .initial:n = \c_zero_dim , belowsep .initial:n = \c_zero_dim , leftsep .initial:n = 1em , rightsep .initial:n = 1em , linewidth .initial:n = \linewidth , hoffset .initial:n = \c_zero_dim , voffset .initial:n = \c_zero_dim , width .initial:n = \c_zero_dim , height .initial:n = \c_zero_dim , ratio .initial:n = \c_one_fp , abovesep .value_required:n = true , belowsep .value_required:n = true , leftsep .value_required:n = true , rightsep .value_required:n = true , linewidth .value_required:n = true , width .value_required:n = true , height .value_required:n = true , hoffset .value_required:n = true , voffset .value_required:n = true , hsep .value_required:n = true , vsep .value_required:n = true , l .value_forbidden:n = true , r .value_forbidden:n = true , c .value_forbidden:n = true , i .value_forbidden:n = true , o .value_forbidden:n = true } \fp_const:Nn \c_@@_c_fp { 0.5 } \cs_new_protected:Npn \@@_swap_true:N #1 { \bool_set_true:N \l_@@_swap_bool \bool_set_eq:NN \l_@@_inner_bool #1 \bool_if:NTF \l_@@_inner_bool { \bool_set_false:N \l_@@_outer_bool } { \bool_set_true:N \l_@@_outer_bool } } \cs_new_protected_nopar:Npn \@@_swap_false:N { \bool_set_false:N \l_@@_swap_bool \fp_set_eq:NN \l_@@_ratio_fp } \cs_new_protected:Npn \@@_unknown_key:n #1 { \regex_match:NnTF \c_@@_integer_regex {#1} { \int_set:Nn \l_@@_top_int } { \@@_unknown_key_error:n } {#1} } \regex_const:Nn \c_@@_integer_regex { \A \d+ \Z } \cs_new_protected_nopar:Npn \@@_unknown_key_error:n { \msg_error:nnn { wstf } { unknown-key } } \msg_new:nnnn { wstf } { unknown-key } { The~key~"#1"~is~unknown~and~is~being~ignored. } { The~package~wrapstuff~does~not~have~a~key~called~"#1".\\ Check~that~you~have~spelled~the~key~name~correctly. } % \end{macrocode} % \end{macro} % % \begin{macro}{\wrapstuffset} % \begin{macrocode} \NewDocumentCommand \wrapstuffset { m } { \keys_set:nn { wrapstuff } {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\wrapstuffclear} % 保险起见,加入 \tn{par} 结束段落,同时结束 \env{wrapstuff@par} 环境。 % \begin{macrocode} \NewDocumentCommand \wrapstuffclear { } { \par \@@_clear: } % \end{macrocode} % \end{macro} % % \begin{macrocode} \cs_if_exist:NTF \ProcessKeyOptions { \ProcessKeyOptions [ wrapstuff ] } { \RequirePackage { l3keys2e } \ProcessKeysOptions { wrapstuff } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \Finale % \endinput