diff options
Diffstat (limited to 'macros/latex/contrib/koma-script/scrlayer-notecolumn.dtx')
-rw-r--r-- | macros/latex/contrib/koma-script/scrlayer-notecolumn.dtx | 1703 |
1 files changed, 1703 insertions, 0 deletions
diff --git a/macros/latex/contrib/koma-script/scrlayer-notecolumn.dtx b/macros/latex/contrib/koma-script/scrlayer-notecolumn.dtx new file mode 100644 index 0000000000..f523537238 --- /dev/null +++ b/macros/latex/contrib/koma-script/scrlayer-notecolumn.dtx @@ -0,0 +1,1703 @@ +% \iffalse^^A meta-comment +% ====================================================================== +% scrlayer-notecolumn.dtx +% Copyright (c) Markus Kohm, 2013-2022 +% +% This file is part of the LaTeX2e KOMA-Script bundle. +% +% This work may be distributed and/or modified under the conditions of +% the LaTeX Project Public License, version 1.3c of the license. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX +% version 2005/12/01 and of this work. +% +% This work has the LPPL maintenance status "author-maintained". +% +% The Current Maintainer and author of this work is Markus Kohm. +% +% This work consists of all files listed in MANIFEST.md. +% ---------------------------------------------------------------------- +% ====================================================================== +%%% From File: $Id: scrlayer-notecolumn.dtx 3915 2022-06-29 07:09:48Z kohm $ +%<identify>%%% (run: identify) +%<init>%%% (run: init) +%<options>%%% (run: options) +%<body>%%% (run: body) +%<final>%%% (run: final) +%<*dtx> +\ifx\ProvidesFile\undefined\def\ProvidesFile#1[#2]{}\fi +\begingroup + \def\filedate$#1: #2-#3-#4 #5${\gdef\filedate{#2/#3/#4}} + \filedate$Date: 2022-06-29 09:09:48 +0200 (Mi, 29. Jun 2022) $ + \def\filerevision$#1: #2 ${\gdef\filerevision{v0.3.#2}} + \filerevision$Revision: 3915 $ + \edef\reserved@a{% + \noexpand\endgroup + \noexpand\ProvidesFile{scrlayer-notecolumn.dtx}% + [\filedate\space\filerevision\space + KOMA-Script package source + }% +\reserved@a +%</dtx> +%<*identify|doc> +%<interface>\NeedsTeXFormat{LaTeX2e}[1995/12/01] +%<interface>\ProvidesPackage{scrlayer-notecolumn}[% +%<doc>\ProvidesFile{scrlayer-notecolumn.tex}[% +% Sometimes following will be replaced by !KOMASCRIPTVERSION: +%!SCRLAYERVERSION +%<interface> package +%</identify|doc> +%<*dtx|identify|doc> + (end user interface for scrlayer)] +%</dtx|identify|doc> +%<*dtx> +\ifx\documentclass\undefined + \input scrdocstrip.tex + \@@input scrkernel-version.dtx + \expandafter\let\csname ifbetawas\expandafter\endcsname + \csname ifbeta\endcsname + \expandafter\let\csname ifbeta\expandafter\endcsname + \csname iftrue\endcsname + \@@input scrstrip.inc + \KOMAdefVariable{COPYRIGHTFROM}{2013} + \KOMAdefVariable{SCRLAYERVERSION}{% + \space\space\filedate\space\filerevision\space KOMA-Script + }% + \generate{\usepreamble\defaultpreamble + \file{scrlayer-notecolumn.sty}{% + \from{scrlayer-notecolumn.dtx}{interface,notecolumn,identify}% + \from{scrlayer.dtx}{interface,notecolumn,init}% + \from{scrlayer-notecolumn.dtx}{interface,notecolumn,init}% + \from{scrlayer.dtx}{interface,notecolumn,options}% + \from{scrlayer-notecolumn.dtx}{interface,notecolumn,options}% + \from{scrlayer.dtx}{interface,notecolumn,body}% + \from{scrlayer-notecolumn.dtx}{interface,notecolumn,body}% + \from{scrlayer-notecolumn.dtx}{interface,notecolumn,final}% + \from{scrlogo.dtx}{logo}% + }% + } + \expandafter\let\csname ifbeta\expandafter\endcsname + \csname ifbetawas\endcsname + \@@input scrstrop.inc +\else + \let\endbatchfile\relax +\fi +\endbatchfile +\documentclass[USenglish]{koma-script-source-doc} +\usepackage{babel} +\usepackage{hvlogos} +\setcounter{StandardModuleDepth}{2} +\begin{document} + \DocInput{scrlayer-notecolumn.dtx} +\end{document} +%</dtx> +% \fi^^A meta-comment +% +% \changes{v0.0}{2013/04/26}{start of interface} +% \changes{v0.3.3532}{2020/09/11}{do not use deprecated interface commands} +% \changes{v3.36}{2022/02/10}{switch over from \cls*{scrdoc} to +% \cls*{koma-script-source-doc}} +% \changes{v3.36}{2022/02/10}{require package \pkg*{scrlogo} instead of +% defining \cs{KOMAScript}} +% +% \GetFileInfo{scrlayer-notecolumn.dtx} +% \title{Providing Note Columns Similar to \cs{marginpar} with +% \href{https://komascript.de}{\KOMAScript} Package +% \pkg*{scrlayer-notecolumn} as Proof of Concept about Layers with +% \href{https://komascript.de}{\KOMAScript} Package \pkg*{scrlayer}} +% \author{\href{mailto:komascript@gmx.info}{Markus Kohm}} +% \date{Version \fileversion{} of \filedate} +% \maketitle +% \begin{abstract} +% This package is only a proof of concept. The main sense of the package is, +% to show the power of layers with \pkg{scrlayer}. It was never intended to +% be used as a productivity package. So there is no support for using +% it. Several features are only rudimentary. Several can be improved. Please +% feel free to fork this package. +% \end{abstract} +% \tableofcontents +% +% \section{User Manual} +% +% You can find the user manuals of \pkg*{scrlayer-notecolumn} in the \KOMAScript{} +% manual, either the German \file{scrguide} or the English \file{scrguien}. +% +% \MaybeStop{\PrintIndex} +% +% \section{Implementation of \pkg*{scrlayer-notecolumn}} +% +% \begin{macrocode} +%<*interface> +% \end{macrocode} +% +% +% \subsection{Initialising some values before the options} +% +% Initialization before all options (even the options from +% \file{scrlayer.dtx}). +% +% Here we test the used pdf\TeX{} primitives. +% \changes{v0.1}{2015/10/07}{ready for renaming \cs{pdfsavepos} and +% \cs{pdflastypos} in luaTeX} +% \changes{v0.1.2483}{2016/06/28}{grouping fixed} +% \begin{macrocode} +%<*init> +\@tempswatrue +\scr@ifundefinedorrelax{pdfsavepos}{% + \scr@ifundefinedorrelax{savepos}{% + \expandafter\@tempswafalse + }{% + \let\scr@savepos\savepos + }% +}{% + \let\scr@savepos\pdfsavepos +} +\scr@ifundefinedorrelax{pdflastypos}{% + \scr@ifundefinedorrelax{lastypos}{% + \expandafter\@tempswafalse + }{% + \let\scr@lastypos\lastypos + }% +}{% + \let\scr@lastypos\pdflastypos +}% +\if@tempswa\else + \PackageError{scrlayer-notecolumn}{missing pdfTeX/luaTeX features}{% + This package needs \string\pdfsavepos\space or \string\savepos\space + and\MessageBreak + \string\pdflastypos\space or \string\lastypos.\MessageBreak + This error is fatal, because usage of the package without these + features\MessageBreak + cannot work!\MessageBreak + You shouldn't continue, but if you'd try, I'll try to abort the LaTeX run + }% + \batchmode\csname @@end\endcsname\end +\fi +%</init> +% \end{macrocode} +% +% +% \subsection{Making a note column} +% +% The package supports a various number of note columns. Each is referenced by +% a unique name. +% +% \begin{command}{\DeclareNoteColumn} +% \begin{description} +% \item[\oarg{option list}:] a comma-separated list of +% \texttt{\meta{key}=\meta{value}} pairs. +% \item[\marg{string}:] the name of the note column (must be fully expandable +% and expand to a string only). +% \end{description} +% That's the primary command for note columns. It defines everything, the note +% column needs. +% \begin{macrocode} +%<*body> +\newcommand*{\DeclareNoteColumn}[2][]{% +% \end{macrocode} +% First of all we need a box register. The contents of the note column will be +% build inside of this register. Since \eTeX{} registers shouldn't be a +% problem. User should use package \pkg{etex}, if he or she runs out of +% registers. Note, that the registers will stay allocated, if the interface +% will be removed! Nevertheless, the name will be destroyed! +% \begin{macrocode} + \@ifundefined{slnc@#2@box}{% + \expandafter\newsavebox\csname slnc@#2@box\endcsname + }{}% +% \end{macrocode} +% There's also a kind of item stack of unprocessed notes for each note column. +% \begin{macrocode} + \@ifundefined{slnc@#2@unprocessed}{% + \@namedef{slnc@#2@unprocessed}{}% + }{}% +% \end{macrocode} +% Next we need a horizontal positions and a width for the note column. Neither +% the horizontal position nor the width are stretchable or shrinkable. The +% position should be variable depending on the page. So it's better to use a +% macro instead of a length. The width isn't more variable than, e.g., the +% text width. So we can use a macro too. Both will be initialised to the +% normal marginal note column later. +% \changes{3.27}{2019/02/14}{initialization of one color stack per note column} +% For color support we also need one color stack per note column. A color +% stack is a feature only available for pdf\TeX{} and lua\TeX{}. +% \begin{macrocode} + \@ifundefined{slnc@#2@colorstack}{% + \scr@ifundefinedorrelax{pdfcolorstackinit}{% + \scr@ifundefinedorrelax{pdffeedback}{}{% + \expandafter\chardef\csname slnc@#2@colorstack\endcsname= + \pdffeedback colorstackinit direct {\slnc@initial@black}% + }% + }{% + \expandafter\chardef\csname slnc@#2@colorstack\endcsname= + \pdfcolorstackinit direct {\slnc@initial@black}% + }% + }{}% +% \end{macrocode} +% If there isn't a font element for the (new) note column, we define a new one +% and add it to the auto-remove code: +% \begin{macrocode} + \@ifundefined{scr@fnt@notecolumn.#2}{% + \@ifundefined{@notecolumn.#2font}{}{% + \PackageInfo{scrlayer-notecolumn}{using already defined + macro\MessageBreak + `\expandafter\string\csname @notecolumn.#2font\endcsname' for font + element\MessageBreak + `notecolumn.#2'% + }% + }% + \newkomafont{notecolumn.#2}{}% + }{% + \PackageInfo{scrlayer-notecolumn}{using already defined font + element\MessageBreak + `notecolumn.#2'% + }% + }% +% \end{macrocode} +% After the initialisation we process the options, that may change the initial +% values. +% \begin{macrocode} + \newcommand*{\slnc@name}{}% + \edef\slnc@name{#2}% + \FamilyExecuteOptions[.definenotecolumn]{KOMAarg}{marginpar,#1}% + \let\slnc@name\relax +% \end{macrocode} +% The values are set up, so they may be used to declare a layer. +% \begin{macrocode} + \DeclareLayer[% + foreground,% + align=tl,% + voffset=1in+\topmargin+\headheight+\headsep,% + height=\dimexpr\textheight+\topskip\relax,% + hoffset=\csname slnc@#2@pos\endcsname,% + width=\csname slnc@#2@width\endcsname,% + contents=\slnc@processnotes{#2}% + ]{notecolumn.#2} +% \end{macrocode} +% We need to add the layer to every page style. The easiest way to do this is +% to add it to the pseudo layer page style \pstyle{@everystyle@}. +% \changes{v0.1.1681}{2014/02/05}{add the layer only once} +% \begin{macrocode} + \IfLayerAtPageStyle{@everystyle@}{notecolumn.#2}{}{% + \AddLayersToPageStyle{@everystyle@}{notecolumn.#2}% + }% +% \end{macrocode} +% Last but not least, we add the new note column to the note column procession +% list. +% \begin{macrocode} + \@cons\slnc@processnotecolumns{{#2}}% +} +% \end{macrocode} +% \begin{macro}{\slnc@initial@black} +% \changes{v0.2.3085}{2019/02/14}{added} +% The initial black is the color used to initialize the color stacks. As long +% as only pdf\TeX{} and lua\TeX{} provide color stacks, we can initialize it +% with \texttt{0 g 0 G}. However it may be better to use the initial +% \cs{current@color} of the used color package. Using \cs{default@color} would +% be even better, but this is not available until \cs{begin\{document\}}. +% \begin{macrocode} +\newcommand*{\slnc@initial@black}{0 g 0 G}% +\AfterPackage*{color}{% + \let\slnc@initial@black\current@color + \AtBeginDocument{\let\slnc@initial@black\default@color}% +}% +\AfterPackage*{xcolor}{% + \let\slnc@initial@black\current@color + \AtBeginDocument{\let\slnc@initial@black\default@color}% +}% +% \end{macrocode} +% \end{macro}^^A \slnc@initial@black +% \begin{macro}{\slnc@processnotecolumns} +% This is a list of all declared note columns in \LaTeX{} syntax (using +% \cs{@cons} and \cs{@elt} etc.). +% \begin{macrocode} +\newcommand*{\slnc@processnotecolumns}{}% +% \end{macrocode} +% \end{macro}^^A \slnc@processnotecolumns +% \begin{macrocode} +%</body> +% \end{macrocode} +% One note column will be declared by default: +% \begin{macrocode} +%<*final> +\DeclareNoteColumn{marginpar} +%</final> +%<*body> +% \end{macrocode} +% \begin{macro}{\slnc@testforpagestylewarning} +% Not all page styles are layer page styles, but only layer page styles can be +% extended by the note column layers. So we warn, if another page style has +% been selected. +% \begin{macrocode} +\newcommand*{\slnc@testforpagestylewarning}{% + \IfLayerPageStyleExists{\currentpagestyle}{}{% + \PackageWarning{scrlayer-notecolumn}{% + output of note columns delayed,\MessageBreak + because with `\currentpagestyle'\MessageBreak + a page style has been selected, that\MessageBreak + isn't a layer page style,% + }% + }% +}% +\AfterSelectAnyPageStyle{\slnc@testforpagestylewarning} +% \end{macrocode} +% \end{macro}^^A \slnc@testforpagestylewarning +% \begin{option}{position,width,font,marginpar,normalmarginpar,reversemarginpar} +% Last but not least we have to define the options for the \meta{option +% list}. +% \begin{macrocode} +\DefineFamilyMember[.definenotecolumn]{KOMAarg} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{position}{% + \@namedef{slnc@\slnc@name @pos}{\dimexpr #1\relax}% + \FamilyKeyStateProcessed +} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{width}{% + \@namedef{slnc@\slnc@name @width}{\dimexpr #1\relax}% + \FamilyKeyStateProcessed +} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{font}{% + \setkomafont{notecolumn.\slnc@name}{#1}% + \FamilyKeyStateProcessed +} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{marginpar}[\relax]{% + \FamilyKeyStateProcessed + \scrlayer@testunexpectedarg{marginpar}{#1}% + \edef\reserved@a{\noexpand\slnc@defpos{\slnc@name}}\reserved@a + \@namedef{slnc@\slnc@name @width}{\marginparwidth}% +} +% \end{macrocode} +% \begin{macro}{\slnc@defpos} +% Little helper for option \opt{marginpar}. The argument is the expanded +% name of the note column. +% \begin{macrocode} +\newcommand*\slnc@defpos[1]{% + \@namedef{slnc@#1@pos}{% + \ifodd\value{page} + \if@reversemargin +% \end{macrocode} +% The reverse marginal note column on odd pages is at the left margin. +% \begin{macrocode} + \dimexpr \oddsidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \else +% \end{macrocode} +% The normal marginal note column on odd pages is the right margin. +% \begin{macrocode} + \dimexpr \oddsidemargin+1in + +\textwidth+\marginparsep\relax + \fi + \else + \if@twoside + \if@reversemargin +% \end{macrocode} +% The reverse marginal note column on even pages is the right margin. +% \begin{macrocode} + \dimexpr \evensidemargin+1in + +\textwidth+\marginparsep\relax + \else +% \end{macrocode} +% The normal marginal note column on even pages is at the left margin. +% \begin{macrocode} + \dimexpr \evensidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \fi + \else +% \end{macrocode} +% \begin{macrocode} +% If not in two-side mode, do the same already done for odd pages. + \if@reversemargin + \dimexpr \oddsidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \else + \dimexpr \oddsidemargin+1in + +\textwidth+\marginparsep\relax + \fi + \fi + \fi + }% +}% +% \end{macrocode} +% \end{macro}^^A \slnc@defpos +% \begin{macrocode} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{normalmarginpar}[\relax]{% + \FamilyKeyStateProcessed + \scrlayer@testunexpectedarg{normalmarginpar}{#1}% + \edef\reserved@a{\noexpand\slnc@defnormalpos{\slnc@name}}\reserved@a + \@namedef{slnc@\slnc@name @width}{\marginparwidth}% +} +% \end{macrocode} +% \begin{macro}{\slnc@defnormalpos} +% Little helper for option \opt{normalmarginpar}. The argument is the +% expanded name of the note column. +% \begin{macrocode} +\newcommand*\slnc@defnormalpos[1]{% + \@namedef{slnc@#1@pos}{% + \ifodd\value{page} +% \end{macrocode} +% The normal marginal note column on odd pages is the right margin. +% \begin{macrocode} + \dimexpr \oddsidemargin+1in + +\textwidth+\marginparsep\relax + \else + \if@twoside +% \end{macrocode} +% The normal marginal note column on even pages is at the left margin. +% \begin{macrocode} + \dimexpr \evensidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \else +% \end{macrocode} +% \begin{macrocode} +% If not in two-side mode, do the same already done for odd pages. + \dimexpr \oddsidemargin+1in + +\textwidth+\marginparsep\relax + \fi + \fi + }% +}% +% \end{macrocode} +% \end{macro}^^A \slnc@defnormalpos +% \begin{macrocode} +\DefineFamilyKey[.definenotecolumn]{KOMAarg}{reversemarginpar}[\relax]{% + \FamilyKeyStateProcessed + \scrlayer@testunexpectedarg{reversemarginpar}{#1}% + \edef\reserved@a{\noexpand\slnc@defreversepos{\slnc@name}}\reserved@a + \@namedef{slnc@\slnc@name @width}{\marginparwidth}% +} +% \end{macrocode} +% \begin{macro}{\slnc@defreversepos} +% Little helper for option \opt{reversemarginpar}. The argument is the +% expanded name of the note column. +% \begin{macrocode} +\newcommand*\slnc@defreversepos[1]{% + \@namedef{slnc@#1@pos}{% + \ifodd\value{page} +% \end{macrocode} +% The reverse marginal note column on odd pages is at the left margin. +% \begin{macrocode} + \dimexpr \oddsidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \else + \if@twoside +% \end{macrocode} +% The reverse marginal note column on even pages is the right margin. +% \begin{macrocode} + \dimexpr \evensidemargin+1in + +\textwidth+\marginparsep\relax + \else +% \end{macrocode} +% \begin{macrocode} +% If not in two-side mode, do the same already done for odd pages. + \dimexpr \oddsidemargin+1in + -\marginparsep-\csname slnc@#1@width\endcsname\relax + \fi + \fi + }% +}% +% \end{macrocode} +% \end{macro}^^A \slnc@defreversepos +% \begin{macrocode} +%</body> +% \end{macrocode} +% \end{option}^^A position … reversemarginpar +% \end{command}^^A \DeclareNoteColumn +% +% \begin{command}{\DeclareNewNoteColumn,\ProvideNoteColumn,\RedeclareNoteColumn} +% Like \cs{DeclareNoteColumn} but with restrictions, if the note column has +% (not) been declared already. +% \begin{macrocode} +%<*body> +\newcommand*{\DeclareNewNoteColumn}[2][]{% + \scr@ifundefinedorrelax{slnc@#2@box}{}{% + \PackageError{scrlayer-notecolumn}{note column `#2' already defined}{% + You may declare only note columns, that haven't been declared + previously using\MessageBreak + \string\DeclareNewNoteColumn. See also the alternatives + \string\RedeclareNoteColumn,\MessageBreak + \string\ProvideNoteColumn, and \string\DeclareNoteColumn.\MessageBreak + Nevertheless, if you'll continue, declaration will be done.% + }% + }% + \DeclareNoteColumn[{#1}]{#2}% +}% +\newcommand*{\ProvideNoteColumn}[2][]{% + \scr@ifundefinedorrelax{slnc@#2@box}{}{% + \PackageInfo{scrlayer-notecolumn}{\string\ProvideNoteColumn{#2} + ignored,\MessageBreak + because of already defined\MessageBreak + not column}% + }{% + \DeclareNoteColumn[{#1}]{#2}% + }% +}% +\newcommand*{\RedeclareNoteColumn}[2][]{% + \scr@ifundefinedorrelax{slnc@#2@box}{% + \PackageError{scrlayer-notecolumn}{note column `#2' undefined}{% + You may declare only note columns, that have been declared + previously using\MessageBreak + \string\RedeclareNoteColumn. See also the alternatives + \string\DeclareNewNoteColumn,\MessageBreak + \string\ProvideNoteColumn, and \string\DeclareNoteColumn.\MessageBreak + Nevertheless, if you'll continue, declaration will be done.% + }% + }{}% + \DeclareNoteColumn[{#1}]{#2}% +}% +%</body> +% \end{macrocode} +% \end{command} +% +% +% \subsection{Setting a note column} +% +% We already have commands to declare note columns. But we also need a command +% to put contents into the note columns and to output the note columns. +% +% \begin{macro}{\tf@slnc} +% \changes{v0.1.2395}{2016/03/25}{write to \file{aux}-file with +% \cs{if@filesw}} +% \begin{macro}{\slnc@initwrite,\slnc@openwrite} +% \changes{v0.1.2928}{2018/02/02}{use \cs{closein} instead of \cs{closeout} +% to close \cs{slnc@file}} +% First of all we need a file to write the notes to. We use the +% \file{aux}-file to write into the file, because we need to read the file +% while the document will be typeset and the same time we need to write into +% the file. Note, that the file will be still reserved on auto-removing the +% interface! +% \begin{macrocode} +%<*body> +\newwrite\tf@slnc +\AtBeginDocument{% + \if@filesw + \immediate\write\@auxout{% + \noexpand\csname slnc@initwrite\noexpand\endcsname + }% + \fi +}% +\AtEndDocument{\let\slnc@initwrite\slnc@openwrite}% +\newcommand*{\slnc@initwrite}{}% +\newcommand*{\slnc@openwrite}{% + \immediate\closein\slnc@file +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + Opening `\jobname.slnc'\MessageBreak + for writing}% +%</trace> + \immediate\openout\tf@slnc\jobname.slnc +} +% \end{macrocode} +% After reading the main \file{aux}-file at |\end{document}|, we again +% calculate the md5 checksum of the \file{slnc}-file. If it has been changed +% we set |\if@tempswa| to |\iftrue| to provocate a rerun message. +% \changes{v0.1.2872}{2018/01/17}{usage of Lua function \texttt{slncmdfivesum}} +% \changes{v0.1.2972}{2018/04/01}{usage of not yet documented Xe\TeX{} +% primitive \cs{mdfivesum}} +% \begin{macrocode} +\AfterReadingMainAux{% + \immediate\closeout\tf@slnc + \begingroup + \scr@ifundefinedorrelax{pdfmdfivesum}{% + \scr@ifundefinedorrelax{mdfivesum}{% + \ifdefined\directlua + \edef\reserved@a{\directlua{slnc.mdfivesum(slnc.slncfile)}}% + \else + \let\reserved@a\relax + \fi + }{% + \edef\reserved@a{\mdfivesum file {\jobname.slnc}}% + }% + }{% + \edef\reserved@a{\pdfmdfivesum file {\jobname.slnc}}% + }% + \ifx\reserved@a\relax + \PackageWarningNoLine{scrlayer-notecolumn}{% + \string\pdfmdfivesum\space unavailable.\MessageBreak + The package needs \string\pdfmdfivesum,\MessageBreak + \string\mdfivesum, or LuaTeX to test whether\MessageBreak + or not one more LaTeX run is needed to place the\MessageBreak + note columns correctly. If these are unavailable\MessageBreak + you have to do the decision without the help\MessageBreak + of the package% + }% + \else + \ifx \slnc@mdfivesum\reserved@a +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + MD5 of current `\jobname.slnc':\MessageBreak + \reserved@a}% +%</trace> + \else +%<*trace> + \PackageWarningNoLine{scrlayer-notecolumn}{% + MD5 of slnc-file changed.\MessageBreak + Last: \slnc@mdfivesum\MessageBreak + New: \space \reserved@a\MessageBreak + At least one more LaTeX rerun needed to\MessageBreak + make note columns right% + }% +%</trace> + \aftergroup\@tempswatrue + \fi + \fi + \endgroup +} +%</body> +% \end{macrocode} +% \changes{v0.3.3600}{2021/05/30}{use of \pkg*{scrwfile}'s never list}% +% The easiest way to make it compatible with \pkg*{scrwfile} is to put it +% on the \emph{never} list. +% \begin{macrocode} +%<*body> +\AfterPackage*{scrwfile}{% + \@ifundefined{scrwfile@never}{\def}{\g@addto@macro}% + \scrwfile@never{slnc}% +} +%</body> +% \end{macrocode} +% \end{macro}^^A \slnc@initwrite,\slnc@openwrite +% \end{macro}^^A \tf@slnc +% +% \begin{command}{\makenote} +% \begin{description} +% \item[\oarg{string}:] the name of the note column the note should be added +% to (must be fully expandable and expand to a string only). The default +% value is |marginpar|. +% \item[\marg{code}:] the code, that should become par of the note +% column. Note, that this will be written protected to a file. So you have +% to use \cs{protect} if a macro shouldn't be expanded while writing or may +% break while writing. +% \end{description} +% There is a star variant with the same parameters, that writes the +% \meta{code} un-expanded. To do so, we need some internal commands. +% \begin{macro}{\slnc@unexpanded,\slnc@makenote} +% \changes{v0.1.2583}{2017/02/08}{added} +% \begin{macrocode} +%<*body> +\newcommand*{\slnc@unexpanded}{} +\let\slnc@unexpanded\detokenize +\newcommand*{\makenote}{% + \kernel@ifstar{\let\slnc@unexpanded\detokenize\slnc@makenote}% + {\let\slnc@unexpanded\@firstofone\slnc@makenote}% +}% +\newcommand{\slnc@makenote}[2][marginpar]{% + \@bsphack + \scr@savepos + \addtocontents{slnc}{% + \string\slnc@note{#1}% + {\noexpand\number\value{slncpage}}% + {\noexpand\number\scr@lastypos}% + {\slnc@unexpanded{#2}}% + }% + \@esphack +}% +% \end{macrocode} +% \begin{counter}{slncpage} +% This counter should be increased once per page with note column. This may +% be done simply at a once per page executed hook of +% \pstyle{@everystyle@}. You should note, that auto-remove wouldn't +% remove the counter. +% \begin{macrocode} +\@ifundefined{c@slncpage}{% + \newcounter{slncpage}% + \AddToLayerPageStyleOptions{@everystyle@}{% + onbackground=\stepcounter{slncpage}% + }% +}{} +%</body> +% \end{macrocode} +% \end{counter}^^A slncpage +% \end{macro}^^A \slnc@makenote,\slnc@unexpanded +% \end{command}^^A \makenote +% +% \begin{macro}{\slnc@processnotes} +% \begin{description} +% \item[\marg{string}:] the name of the note column (must be fully expandable +% an expand to a string only). +% \end{description} +% Each note column typesets the notes with this command. It works in following +% steps: +% \begin{macrocode} +%<*body> +\newcommand*{\slnc@processnotes}[1]{% +% \end{macrocode} +% Read as long notes from the notes file until the number at \#2 of +% \cs{slnc@note} in the file is greater than \cnt{slncpage}. Put all +% these to the corresponding unprocessed list. +% \begin{macrocode} + \begingroup + \slnc@readnotes{\value{slncpage}}% +% \end{macrocode} +% Process the unprocessed list of the current note column +% \begin{macrocode} + \expandafter\let\expandafter\reserved@a + \csname slnc@#1@unprocessed\endcsname + \expandafter\global + \expandafter\let\csname slnc@#1@unprocessed\endcsname\@empty + \def\slnc@notesyncfonttest##1{% + \ifhmode + \PackageError{scrlayer-notecolumn}{% + illegal font setting for `notecolumn.##1'% + }{% + Current setting of font for `notecolumn.##1' switches + from\MessageBreak + vertical mode to horizontal mode. This is + illegal!\MessageBreak + You have to change the font setting to fix + this.\MessageBreak + If you'll continue vertical alignment of notes may fail% + }% + \par\vskip-\dimexpr \baselineskip+\parskip\relax + \fi + }% + \long\def\slnc@note##1##2##3##4{% +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): ##2<=\theslncpage?}% + \ifnum ##2>\value{slncpage}\relax +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): no: unprocess note}% + \expandafter\g@addto@macro\csname slnc@#1@unprocessed\endcsname{% + \slnc@note{##1}{##2}{##3}{##4}% + }% + \else + \ifnum ##2<\value{slncpage}\relax + \PackageWarning{scrlayer-notecolumn}{note of type `#1' delayed}% + \fi + \boxmaxdepth\maxdepth + \expandafter\setbox\csname slnc@#1@box\endcsname\vbox{% + \expandafter\hsize\csname slnc@#1@width\endcsname + \normalfont\normalsize +% \end{macrocode} +% \changes{v0.2.3085}{2019/02/14}{using color stack if available} +% If a color stack is available we switch to it before changing the font. So a +% color definition inside the font would overwrite every color change inside +% the column! But if we don't have a color stack, color switching is not +% permitted! +% \begin{macrocode} + \slnc@switchcolorstack{#1}% + {% + \usekomafont{notecolumn.#1}{% + \slnc@notesyncfonttest{#1}% + \expandafter\ifvoid\csname slnc@#1@box\endcsname + \expandafter\setbox\csname slnc@#1@box\endcsname\vbox{% + \kern\dimexpr\topskip-\baselineskip\relax + }% + \fi +% \end{macrocode} +% \changes{v0.1}{2015/10/07}{ready for renaming \cs{pdfpageheight} in +% luaTeX} +% From lua\TeX~0.80.1 \cs{pdfpageheight} will be renamed into +% \cs{pageheight}. So we have to do an extra test for the new primitive. +% \begin{macrocode} + \scr@ifundefinedorrelax{pdfpageheight}{% + \scr@ifundefinedorrelax{pageheight}{% + \@tempdima=\paperheight + }{% + \@tempdima=\pageheight + }% + }{% + \@tempdima=\pdfpageheight + }% + \@tempdima=\dimexpr \@tempdima-##3sp + -1in-\topmargin + -\headheight-\headsep + -\baselineskip + \relax + \@tempdimb=\dimexpr \expandafter\ht\csname slnc@#1@box\endcsname + +\expandafter\dp\csname slnc@#1@box\endcsname + \relax + \ifdim\@tempdima<\@tempdimb +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + Note moved down from\MessageBreak + \the\@tempdima\space to \the\@tempdimb\MessageBreak + at note box `#1' + }% +%</trace> + \else + \ifdim\@tempdima>\@tempdimb +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + Adding vertical white space from\MessageBreak + \the\@tempdimb\space to \the\@tempdima\MessageBreak + into note box `#1' + }% +%</trace> + \expandafter\setbox\csname slnc@#1@box\endcsname + \vbox {% + \expandafter\unvbox\csname slnc@#1@box\endcsname + \kern\dimexpr\@tempdima-\@tempdimb\relax + }% + \fi + \fi + \expandafter\ifvoid\expandafter\csname slnc@#1@box\endcsname + \else + \@tempdima\dimexpr + \dp\strutbox + -\dp\csname slnc@#1@box\endcsname + \relax + \expandafter\unvbox\csname slnc@#1@box\endcsname + \ifdim\@tempdima>\z@ \kern\@tempdima\fi + \fi +% \end{macrocode} +% \changes{v0.1.2582}{2017/02/08}{restore several commands} +% Some commands have to be restored when processing the note. +% \begin{macrocode} + \slnc@restoreinnote + \strut\ignorespaces ##4\par + }% + }% + }% + \fi + }% + \def\slnc@sync##1##2##3##4{% + \ifnum ##2>\value{slncpage}\relax + \expandafter\g@addto@macro\csname slnc@#1@unprocessed\endcsname{% + \slnc@sync{##1}{##2}{##3}{}% + }% + \else + \if@filesw + \expandafter\setbox\csname slnc@#1@box\endcsname\vbox{% + \expandafter\unvbox\csname slnc@#1@box\endcsname + \scr@savepos + \protected@write\@auxout{}{% + \string\newlabel{notecolumn.##1.##3.syncnote.label}{% + {% + \noexpand\number\scr@lastypos + }{\thepage}% + }% + }% + }% + \fi + \fi + }% + \reserved@a + \expandafter\ifvoid\csname slnc@#1@box\endcsname +%<*trace> + \PackageInfo{scrlayer-notecolumn}{Note box `#1' empty}% +%</trace> + \else + \ifdim \dimexpr \expandafter\ht\csname slnc@#1@box\endcsname + +\expandafter\dp\csname slnc@#1@box\endcsname + \relax >\textheight\relax +%<*trace> + \PackageInfo{scrlayer-notecolumn}{Split note box `#1'}% +%</trace> + \splittopskip\topskip + \splitmaxdepth\baselineskip +% \end{macrocode} +% Bring back the colors: +% \changes{v0.2.3085}{2019/02/14}{\cs{slnc@switchcolorstack} added} +% \begin{macrocode} + \usekomafont{notecolumn.#1}{% + \expandafter\vsplit\csname slnc@#1@box\endcsname to + \textheight\relax + }% + \expandafter\ifvoid\csname slnc@#1@box\endcsname + \else + \expandafter\setbox\csname slnc@#1@box\endcsname\vbox{% + \slnc@switchcolorstack{#1}% + \expandafter\unvbox\csname slnc@#1@box\endcsname + }% + \fi + \else +%<*trace> + \PackageInfo{scrlayer-notecolumn}{Flush note box `#1'}% +%</trace> +% \end{macrocode} +% Bring back the colors: +% \changes{v0.2.3085}{2019/02/14}{\cs{slnc@switchcolorstack} added} +% \begin{macrocode} + \usekomafont{notecolumn.#1}{% + \slnc@switchcolorstack{#1}% + \expandafter\box\csname slnc@#1@box\endcsname% + }% + \fi + \fi + \expandafter\global + \expandafter\setbox\csname slnc@#1@box\expandafter\endcsname + \expandafter\box\csname slnc@#1@box\endcsname + \endgroup +} +% \end{macrocode} +% \begin{macro}{\slnc@switchcolorstack} +% \changes{v0.2.3085}{2019/02/14}{added} +% This either redefines \cs{set@color} or switches to the color stack of the +% note column given by the argument. +% \begin{macrocode} +\newcommand*{\slnc@switchcolorstack}[1]{% + \scr@ifundefinedorrelax{slnc@#1@colorstack}{% + \def\set@color{% + \PackageWarningNoLine{scrlayer-notecolumn}{% + unsupported change of color!\MessageBreak + It seems you are using a TeX engine,\MessageBreak + that does not support switching the\MessageBreak + color stack like pdfTeX or luaTeX do.\MessageBreak + Because of this, usage of \string\color,\MessageBreak + \string\textcolor\space etc. inside a note + column\MessageBreak + is not supported% + }% + }% + }{% + \scr@ifundefinedorrelax{@pdfcolorstack}{% + }{% + \expandafter\let\expandafter\@pdfcolorstack + \csname slnc@#1@colorstack\endcsname + }% + \scr@ifundefinedorrelax{pdfcolorstack}{% + \scr@ifundefinedorrelax{pdfextension}{% + \PackageError{scrlayer-notecolumm}{% + color stack defined but not usable% + }{% + \expandafter\string + \csname slnc@#1@colorstack\endcsname\space defined + \MessageBreak + but neither \string\pdfcolorstack\space nor + \string\pdfextension.\MessageBreak + This should never happen!% + }% + }{% + \pdfextension colorstack + \csname slnc@#1@colorstack\endcsname current\relax + }% + }{% + \pdfcolorstack + \csname slnc@#1@colorstack\endcsname current\relax + }% + }% +}% +% \end{macrocode} +% \end{macro}^^A \slnc@switchcolorstack +% \begin{command}{\restoreinnote} +% \changes{v0.1.2582}{2017/02/08}{added} +% \begin{macro}{\slnc@restoreinnote} +% \changes{v0.1.2582}{2017/02/08}{added} +% Some commands have to be restored while processing the notes. By default +% these are \cs{label}, \cs{index}, \cs{glossary}. More can be added using +% \cs{restoreinnote}. The storage is \cs{slnc@restoreinnote}. +% \begin{macrocode} +\newcommand*{\slnc@restoreinnote}{} +\let\slnc@restoreinnote\@empty +\newcommand*\restoreinnote[1]{% + \AtBeginDocument{% + \expandafter\newcommand\expandafter*\csname slnc\string#1\endcsname{}% + \expandafter\let\csname slnc\string#1\endcsname#1% + \g@addto@macro\slnc@restoreinnote{% + \expandafter\let\expandafter#1\csname slnc\string#1\endcsname + }% + }% +} +\@onlypreamble\restoreinnote +\restoreinnote\label +\restoreinnote\index +\restoreinnote\glossary +% \end{macrocode} +% \end{macro}^^A \slnc@restoreinnote +% \end{command}^^A \restoreinnote +% \begin{macro}{\slnc@readnotes} +% Read as long notes from the notes file until the number at \#2 of +% \cs{slnc@note} or \cs{slnc@sync} in the file is greater than +% \cnt{slncpage}. Put all these to the corresponding unprocessed list. +% \begin{macro}{\slnc@catcodes} +% \changes{v0.3}{2019/03/02}{added} +% We need a helper macro \cs{slnc@catcodes} to restore (some of) the catcodes +% before reading from file. +% \begin{macrocode} +\newcommand*{\slnc@catcodes}{}% +\AtBeginDocument{% + \begingroup + \def\do#1{% + \protected@xdef\slnc@catcodes{\slnc@catcodes + \catcode`\protect#1=\the\catcode`#1\relax + }% + }% + \dospecials + \let\protect\noexpand + \xdef\slnc@catcodes{\slnc@catcodes\catcode`\protect\@=11\relax}% + \endgroup +} +% \end{macrocode} +% \end{macro}^^A \slnc@catcodes +% \begin{macrocode} +\newcommand*\slnc@readnotes[1]{% + \ifeof\slnc@file\else + \ifnum \number #1<\slnc@unprocessed\relax + \@tempswafalse + \else + \@tempswatrue + \fi + \@whilesw\if@tempswa\fi{% + \begingroup + \slnc@catcodes + \endlinechar\m@ne + \read\slnc@file to\reserved@a + \edef\reserved@a{% + \endgroup + \noexpand\def\noexpand\reserved@a{% + \unexpanded\expandafter{\reserved@a}% + }% + }% + \reserved@a + \expandafter\slnc@iofv\expandafter\reserved@b\reserved@a + \@empty\@empty\@empty\@empty\@empty + \@tempswafalse + \@for\reserved@c :={\slnc@note },{\slnc@sync }\do{% + \ifx\reserved@b\reserved@c \@tempswatrue\fi + }% + \if@tempswa + \@tempswafalse + \expandafter\slnc@iiiofv\expandafter\reserved@b\reserved@a + \@empty\@empty\@empty\@empty\@empty + \ifx\reserved@b\@empty + \PackageError{scrlayer-notecolumn}{internal syntax error}{% + Unexpected syntax of file `\jobname.slnc'.\MessageBreak + Second argument should be a number.\MessageBreak + I don't know what to do with\MessageBreak + \expandafter\detokenize\expandafter{\reserved@a}% + }% + \@tempswatrue + \else + \global\let\slnc@unprocessed\reserved@b + \expandafter\slnc@iiofv\expandafter\reserved@b\reserved@a + \@empty\@empty\@empty\@empty\@empty + \@ifundefined{slnc@\reserved@b @unprocessed}{% + \PackageWarning{scrlayer-notecolumn}{% + column `\reserved@b' undefined.\MessageBreak + You should declare the column before the usage.\MessageBreak + Notes will be lost% + }% + }{% + \expandafter\g@addto@macro + \csname slnc@\reserved@b @unprocessed\expandafter\endcsname + \expandafter{% + \reserved@a + }% + }% + \ifnum \number #1<\slnc@unprocessed\relax + \@tempswafalse + \else + \@tempswatrue + \fi + \fi + \else +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + Ignoring `\expandafter\detokenize\expandafter{\reserved@a}'}% +%</trace> + \@tempswatrue + \fi + \ifeof\slnc@file\@tempswafalse\fi + }% + \fi +}% +% \end{macrocode} +% \end{macro}^^A \slnc@readnotes +% \begin{macro}{\slnc@iofv,\slnc@iiofv,\slnc@iiiofv} +% \begin{macrocode} +\newcommand\slnc@iofv[6]{\def#1{#2}}% +\newcommand\slnc@iiofv[6]{\def#1{#3}}% +\newcommand\slnc@iiiofv[6]{\def#1{#4}}% +% \end{macrocode} +% \end{macro}^^A \slnc@iofv … \slnc@iiiofv +% \begin{macro}{\slnc@unprocessed} +% The \#2 of the last read note column from notes file. +% \begin{macrocode} +\newcommand*{\slnc@unprocessed}{0}% +%</body> +% \end{macrocode} +% \begin{macro}{\slnc@file} +% The input file with the unprocessed notes. +% \changes{v0.1.2928}{2018/02/02}{use \cs{closein} instead of \cs{closeout} +% to close \cs{slnc@file}} +% \begin{macro}{\slnc@mdfivesum} +% \changes{v0.1.2872}{2018/01/17}{definition and usage of Lua function +% \texttt{slncmdfivesum}} +% \changes{v0.1.2972}{2018/04/01}{usage of not yet documented \XeTeX{} +% primitive \cs{mdfivesum}} +% \changes{v0.3.3591}{2021/03/25}{Lua function name changed to +% \texttt{slnc.mdfivesum}} +% \changes{v0.3.3591}{2021/03/25}{new Lua variable \texttt{slnc.slncfile}} +% The MD5 sum of the file before opening it for reading. +% \begin{macrocode} +%<*body> +\newcommand*{\slnc@mdfivesum}{} +\let\slnc@mdfivesum\@empty +\scr@ifundefinedorrelax{pdfmdfivesum}{% + \scr@ifundefinedorrelax{mdfivesum}{% + \ifdefined\directlua + \directlua{% + slnc = slnc or {} + function slnc.mdfivesum(filename) + local fh = io.open(filename,"rb") + if fh then + local sum=md5.sumhexa(fh:read("*a")) + tex.sprint(sum) + fh:close() + end + end + if (string.sub(tex.jobname,1,1) == '"') + and (string.sub(tex.jobname,string.len(tex.jobname),-1) == '"') + then + slnc.slncfile = string.sub(tex.jobname,2,-2) + else + slnc.slncfile = tex.jobname + end + slnc.slncfile = slnc.slncfile .. '.slnc' + }% + \xdef\slnc@mdfivesum{\directlua{slnc.mdfivesum(slnc.slncfile)}}% + \fi + }{% + \xdef\slnc@mdfivesum{\mdfivesum file {\jobname.slnc}}% + }% +}{% + \xdef\slnc@mdfivesum{\pdfmdfivesum file {\jobname.slnc}}% +}% +%<*trace> +\scr@ifundefinedorrelax{slnc@mdfivesum}{}{% + \PackageInfo{scrlayer-notecolumn}{% + MD5 of last `\jobname.slnc':\MessageBreak + \slnc@mdfivesum}% +}% +%</trace> +\newread\slnc@file +\immediate\openin\slnc@file \jobname.slnc +%</body> +% \end{macrocode} +% \end{macro}^^A \slnc@mdfivesum +% \end{macro}^^A \slnc@file +% \end{macro}^^A \slnc@unprocessed +% \end{macro}^^A \slnc@processnotes +% +% \begin{option}{autoclearnotecolumns} +% \begin{macro}{\ifslnc@autoclearnotecolumns,\slnc@autoclearnotecolumnstrue, +% \slnc@autoclearnotecolumnsfalse} +% \begin{macrocode} +%<*options> +\KOMA@ifkey{autoclearnotecolumns}{slnc@autoclearnotecolumns} +\slnc@autoclearnotecolumnstrue +%</options> +%<*final> +\let\reserved@a\clearpage +\def\clearpage{% + \ifslnc@autoclearnotecolumns\clearnotecolumns\relax\fi +}% +\expandafter\g@addto@macro\expandafter\clearpage\expandafter{\reserved@a} +%</final> +% \end{macrocode} +% \end{macro} +% \end{option} +% +% \begin{command}{\clearnotecolumn} +% \begin{description} +% \item[\oarg{string}:] the name of the note column (must be fully +% expandable and expand to a string only). Default is |marginpar|. +% \end{description} +% Output as many (empty) pages as needed to output all unprocessed notes of +% one note column. Note, that the output of the first page may result in more +% unprocessed notes. But the output of the following (empty) pages shouldn't. +% \begin{macrocode} +%<*body> +\newcounter{slnc@clearnote@label}% +\newcommand*\clearnotecolumn[1][marginpar]{% + \begingroup + \slnc@autoclearnotecolumnsfalse +% \end{macrocode} +% First of all we need to know the note column page of this page. +% \begin{macrocode} + \stepcounter{slnc@clearnote@label}% + \if@filesw + \protected@write\@auxout{% + \let\theslncpage\relax + \let\slnc@voidtest\relax + }{% + \string\newlabel{notecolumn.\theslnc@clearnote@label}% + {{\theslncpage}{\slnc@voidtest{#1}}}% + }% + \fi + \scr@ifundefinedorrelax{r@notecolumn.\theslnc@clearnote@label}{% + \PackageInfo{scrlayer-notecolumn}{% + Using estimated to low value for clearing\MessageBreak + note colum `#1'% + } + \edef\slnc@cmp@value{\the\value{slncpage}}% + \let\reserved@a\z@ + }{% + \edef\reserved@a{% + \@nameuse{r@notecolumn.\theslnc@clearnote@label}\@empty\@empty + }% + \edef\slnc@cmp@value{\expandafter\slnc@firstof\reserved@a\@nil}% + \edef\reserved@a{\expandafter\slnc@secondof\reserved@a\@nil}% + }% +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + TRACE (slnc): clearnote=\@nameuse{theslnc@clearnote@label}, + abspage=\the\value{slncpage}, until page=\slnc@cmp@value, + process=\reserved@a, pagetotal=\the\pagetotal, topskip=\the\topskip}% +%</trace> + \ifvmode\ifdim \pagetotal<\topskip +% \end{macrocode} +% \cs{clearpage} wouldn't result in a new page, so we do not have to output +% the notes of this page but only until the previous. +% \begin{macrocode} + \edef\slnc@cmp@value{\the\numexpr\slnc@cmp@value-1}% +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): until page=\slnc@cmp@value}% + \fi\fi + \ifnum \reserved@a=\z@ +% \end{macrocode} +% Next we read all notes until the end of the current page, but only +% if a \cs{clearpage} wouldn't result in a new page. +% \begin{macrocode} + \ifvmode + \ifdim \pagetotal<\topskip + \else + \slnc@readnotes{\slnc@cmp@value}% + \fi + \else + \slnc@readnotes{\slnc@cmp@value}% + \fi + \begingroup + \aftergroup\@tempswafalse + \long\def\slnc@note##1##2##3##4{% + \ifnum ##2>\slnc@cmp@value\relax \else \aftergroup\@tempswatrue\fi + }% + \let\slnc@sync\slnc@note + \csname slnc@#1@unprocessed\endcsname + \endgroup + \else + \PackageInfo{scrlayer-notecolumn}{% + box of note column `#1'\MessageBreak + not empty after page of \string\clearnotecolumn}% + \@tempswatrue + \fi + \if@tempswa +% \end{macrocode} +% Yes, we have! +% \begin{macrocode} + \IfLayerPageStyleExists{\currentpagestyle}{}{% + \PackageWarning{scrlayer-notecolumn}{% + \string\clearnotecolumn\space while active non-layer page + style.\MessageBreak + Activate empty page style until note column\MessageBreak + has been cleared% + }% + \pagestyle{empty}% + }% + \@tempswatrue + \fi + \@whilesw\if@tempswa\fi{% +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): add \string\clearpage}% +% \end{macrocode} +% Yes, we have (maybe again)! +% \begin{macrocode} + \clearpage + \expandafter\ifcase \slnc@voidtest{#1}% + \begingroup + \aftergroup\@tempswafalse + \long\def\slnc@note##1##2##3##4{% + \ifnum ##2>\slnc@cmp@value\relax \else \aftergroup\@tempswatrue\fi + }% + \let\slnc@sync\slnc@note + \csname slnc@#1@unprocessed\endcsname + \endgroup + \else + \@tempswatrue + \fi + \if@tempswa +% \end{macrocode} +% And we still have: So we have to output one more page. +% \begin{macrocode} + \null + \fi + }% + \endgroup +} +% \end{macrocode} +% \begin{macro}{\slnc@firstof,\slnc@secondof} +% We need these little helpers, because some packages like +% \pkg{hyperref} extend the label mechanism by additional arguments. +% \begin{macrocode} +\newcommand*{\slnc@firstof}{} +\def\slnc@firstof#1#2\@nil{#1}% +\newcommand*{\slnc@secondof}{} +\def\slnc@secondof#1#2#3\@nil{#2}% +% \end{macrocode} +% \end{macro}^^A \slnc@firstof,\slnc@secondof +% \begin{macro}{\slnc@voidtest} +% \begin{description} +% \item[\marg{string}:] the name of a note column (must be fully +% expandable and expand to a string only). +% \end{description} +% If the box of the note column is empty/void it returns \cs{z@} otherwise +% \cs{@ne}. +% \begin{macrocode} +\newcommand*{\slnc@voidtest}[1]{% + \expandafter\ifvoid \csname slnc@#1@box\endcsname \z@\else \@ne\fi +} +%</body> +% \end{macrocode} +% \end{macro}^^A \slnc@voidtest +% \end{command}^^A \clearnotecolumn +% +% \begin{command}{\clearnotecolumns} +% \changes{v3.26}{2018/08/29}{\cs{scr@trim@spaces} added} +% \changes{v3.26}{2018/08/29}{removed spurious \cs{expandafter}} +% \begin{description} +% \item[\oarg{string list}:] comma separated list of note column names (must +% be fully expandable and each element must expand to a string only, that is +% the name of a note column); if omitted or empty all note columns will be +% used. +% \end{description} +% Output as many (empty) pages as needed to output all unprocessed notes of +% all (given) note columns. Note, that the output of the first page may +% result in more unprocessed notes. But the output of the following (empty) +% pages shouldn't. +% \begin{macrocode} +%<*body> +\newcommand*\clearnotecolumns[1][\relax]{% + \begingroup + \slnc@autoclearnotecolumnsfalse + \ifx\relax#1\relax\else + \let\slnc@processnotecolumns\@empty + \edef\reserved@a{#1}% + \@for\reserved@a:=\reserved@a\do {% + \scr@trim@spaces\reserved@a + \ifx\reserved@a\@empty\else + \expandafter\l@addto@macro\expandafter\slnc@processnotecolumns + \expandafter{\expandafter\@elt\expandafter{\reserved@a}}% + \fi + }% + \fi +% \end{macrocode} +% First of all we need to know the note column page of this page. +% \begin{macrocode} + \stepcounter{slnc@clearnote@label}% + \if@filesw + \begingroup + \def\@elt##1{+\slnc@voidtest{##1}}% + \protected@write\@auxout{% + \let\theslncpage\relax + \let\slnc@voidtest\relax + }{% + \string\newlabel{notecolumn.\theslnc@clearnote@label}% + {{\theslncpage}{\numexpr \slnc@processnotecolumns\relax}}% + }% + \endgroup + \fi + \scr@ifundefinedorrelax{r@notecolumn.\theslnc@clearnote@label}{% + \begingroup + \def\@elt##1{, `##1'}% + \PackageInfo{scrlayer-notecolumn}{% + Using estimated to low value for\MessageBreak + clearing note colums\MessageBreak + \expandafter\@gobble\slnc@processnotecolumns + }% + \endgroup + \edef\slnc@cmp@value{\the\value{slncpage}}% + \let\reserved@a\z@ + }{% + \edef\reserved@a{% + \@nameuse{r@notecolumn.\theslnc@clearnote@label}\@empty\@empty + }% + \edef\slnc@cmp@value{\expandafter\slnc@firstof\reserved@a\@nil}% + \edef\reserved@a{\expandafter\slnc@secondof\reserved@a\@nil}% + }% +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + TRACE (slnc): clearnote=\@nameuse{theslnc@clearnote@label}, + abspage=\theslncpage, until page=\slnc@cmp@value, + process=\reserved@a, pagetotal=\the\pagetotal, topskip=\the\topskip}% +%</trace> + \ifvmode\ifdim \pagetotal<\topskip +% \end{macrocode} +% \cs{clearpage} wouldn't result in a new page, so we do not have to output +% the notes of this page but only until the previous. +% \begin{macrocode} + \edef\slnc@cmp@value{\the\numexpr\slnc@cmp@value-1}% +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): until page=\slnc@cmp@value}% + \fi\fi + \ifnum \reserved@a=\z@ +% \end{macrocode} +% Next we read all notes until the end of the current page, but only +% if a \cs{clearpage} wouldn't result in a new page. +% \begin{macrocode} + \ifvmode + \ifdim \pagetotal<\topskip + \else + \slnc@readnotes{\slnc@cmp@value}% + \fi + \else + \slnc@readnotes{\slnc@cmp@value}% + \fi + \begingroup + \aftergroup\@tempswafalse + \long\def\slnc@note##1##2##3##4{% + \ifnum ##2>\slnc@cmp@value\relax \else \aftergroup\@tempswatrue\fi + }% + \let\slnc@sync\slnc@note + \def\@elt##1{\csname slnc@##1@unprocessed\endcsname}% + \slnc@processnotecolumns + \endgroup + \else + \PackageInfo{scrlayer-notecolumn}{% + box of at least one note column\MessageBreak + not empty after page of \string\clearnotecolumns}% + \@tempswatrue + \fi + \if@tempswa +% \end{macrocode} +% Yes, we have! +% \begin{macrocode} + \IfLayerPageStyleExists{\currentpagestyle}{}{% + \PackageWarning{scrlayer-notecolumn}{% + \string\clearnotecolumns\space while active non-layer page + style.\MessageBreak + Activate empty page style until note column\MessageBreak + has been cleared% + }% + \pagestyle{empty}% + }% + \@tempswatrue + \fi + \@whilesw\if@tempswa\fi{% +%<trace> \PackageInfo{scrlayer-notecolumn}{TRACE (slnc): adding \string\clearpage}% +% \end{macrocode} +% Yes, we have (maybe again)! +% \begin{macrocode} + \clearpage + \begingroup + \def\@elt##1{+\slnc@voidtest{##1}}% + \ifcase \numexpr \slnc@processnotecolumns\relax + \aftergroup\@tempswafalse + \long\def\slnc@note##1##2##3##4{% + \ifnum ##2>\slnc@cmp@value\relax \else \aftergroup\@tempswatrue\fi + }% + \let\slnc@sync\slnc@note + \def\@elt##1{\csname slnc@##1@unprocessed\endcsname}% + \slnc@processnotecolumns + \else + \aftergroup\@tempswatrue + \fi + \endgroup + \if@tempswa +% \end{macrocode} +% And we still have: So we have to output one more page. +% \begin{macrocode} + \null + \fi + }% + \endgroup +} +%</body> +% \end{macrocode} +% \end{command}^^A \clearnotecolumns +% +% +% \subsection{Syncronisation of text and note} +% \label{sec:scrlayer-notecolumn.sync} +% +% Until yet we have the text and we have note columns. Normally note entries +% to a note column are in sync with the text position, that makes the +% note. But if there are collisions the sync may be lost. In this case the +% note may be later (but never earlier), so we need a mechanism to force +% synchronisation of the text with the note. +% +% \begin{command}{\syncwithnotecolumn,\syncwithnotecolumns} +% \changes{v3.26}{2018/08/29}{\cs{scr@trim@spaces} added} +% \changes{v3.26}{2018/08/29}{removed spurious \cs{expandafter}} +% \begin{description} +% \item[\oarg{string}:] the name of the note column to sync with (this must be +% fully expandable and expand to the name of a note column). By default sync +% with note column |marginpar|. +% \end{description} +% \begin{counter}{slnc@syncpoint} +% Add at the \LaTeX{} run after the next \LaTeX{} run as much space to the +% text (not the note column!) as needed to reach the next position at the +% note column. This is not the same like \cs{clearnotecolumn}, because it +% doesn't need to go to the next page, but it needs at least three \LaTeX{} +% runs to terminate. +% \begin{macrocode} +%<*body> +\newcounter{slnc@syncpoint}% +\newcommand*{\syncwithnotecolumn}[1][marginpar]{% + \begingroup + \edef\reserved@a{\endgroup\noexpand\syncwithnotecolumns[{#1}]}% + \reserved@a +} +\newcommand*{\syncwithnotecolumns}[1][\relax]{% + \begingroup + \ifx\relax#1\relax\else + \let\slnc@processnotecolumns\@empty + \edef\reserved@a{#1}% + \@for\reserved@a:=\reserved@a\do {% + \scr@trim@spaces\reserved@a + \ifx\reserved@a\@empty\else + \expandafter\l@addto@macro\expandafter\slnc@processnotecolumns + \expandafter{\expandafter\@elt\expandafter{\reserved@a}}% + \fi + }% + \fi + \stepcounter{slnc@syncpoint}% + \def\@elt##1{% + \addtocontents{slnc}{% + \string\slnc@sync{##1}% + {\noexpand\number\value{slncpage}}% + {\theslnc@syncpoint}% + {}% + }% + }% + \slnc@processnotecolumns + \ifvmode + \let\slnc@voffset\@empty% + \expandafter\@firstofone + \else + \PackageWarning{scrlayer-notecolumn}{% + \string\syncwithnotecolumn\space in hmode.\MessageBreak + Using \string\syncwithnotecolumn\space in horizontal\MessageBreak + mode may result in unwanted vertical\MessageBreak + space inside paragraphs and may lost\MessageBreak + colors of text of notes. \space So perhaps you\MessageBreak + should move \string\syncwithnotecolumn\space before\MessageBreak + or after the paragraph% + }% + \let\slnc@voffset\@empty%\def\slnc@voffset{-\number\baselineskip}% + \expandafter\slnc@vadjust + \fi + {% + \if@filesw + \scr@savepos + \protected@write\@auxout{}{% + \string\newlabel{notecolumn.\theslnc@syncpoint.synctext.label}{% + {% + \noexpand\number + \numexpr \scr@lastypos\slnc@voffset\relax + }{\thepage}% + }% + }% + \fi + \@ifundefined{r@notecolumn.\theslnc@syncpoint.synctext.label}{% + \PackageInfo{scrlayer-notecolumn}{% + No text label for \string\syncwithnotecolumn.\MessageBreak + Need rerun to sync position}% + }{% + \edef\reserved@a{% + \@nameuse{r@notecolumn.\theslnc@syncpoint.synctext.label}% + \@empty\@empty + }% + \edef\slnc@textpos{\expandafter\slnc@firstof\reserved@a\@nil}% + \edef\slnc@textpage{\expandafter\slnc@secondof\reserved@a\@nil}% + \let\slnc@notepos\slnc@textpos + \let\slnc@notepage\slnc@textpage + \def\@elt##1{% + \@ifundefined{r@notecolumn.##1.\theslnc@syncpoint.syncnote.label}{% + \PackageInfo{scrlayer-notecolumn}{% + No note label for sync with note column\MessageBreak + `##1'.\MessageBreak + Need rerun to sync position}% + \G@refundefinedtrue + }{% + \edef\reserved@a{% + \@nameuse{r@notecolumn.##1.\theslnc@syncpoint.syncnote.label}% + \@empty\@empty + }% + \edef\reserved@b{\expandafter\slnc@firstof\reserved@a\@nil}% + \edef\reserved@c{\expandafter\slnc@secondof\reserved@a\@nil}% + \ifnum \slnc@notepage<\reserved@c\relax + \let\slnc@notepos=\reserved@b + \let\slnc@notepage=\reserved@c + \else + \ifnum \slnc@notepage=\reserved@c\relax + \ifnum \slnc@notepos>\reserved@b + \let\slnc@notepos=\reserved@b + \let\slnc@notepage=\reserved@c + \fi + \fi + \fi + }% + }% + \slnc@processnotecolumns + \ifnum\slnc@textpage>\slnc@notepage\relax + \PackageInfo{scrlayer-notecolumn}{% + Last note page before last text page.\MessageBreak + Need rerun to sync position}% + \else + \ifnum\slnc@textpage<\slnc@notepage\relax + \@whilenum \slnc@textpage<\slnc@notepage\do {% + \newpage\null\vskip-\dimexpr \baselineskip+\parskip\relax + \edef\slnc@textpage{\the\numexpr\slnc@textpage+1\relax}% + }% +% \end{macrocode} +% \changes{v0.1}{2015/10/07}{ready for renaming \cs{pdfpageheight} in +% luaTeX} +% From lua\TeX~0.80.1 \cs{pdfpageheight} will be renamed into +% \cs{pageheight}. So we have to do an extra test for the new primitive. +% \begin{macrocode} + \scr@ifundefinedorrelax{pdfpageheight}{% + \scr@ifundefinedorrelax{pageheight}{% + \@tempdima=\paperheight + }{% + \@tempdima=\pageheight + }% + }{% + \@tempdima=\pdfpageheight + }% + \@tempdima=\dimexpr \@tempdima + -\topmargin-1in + -\headheight-\headsep + -\topskip+\baselineskip + \relax + \edef\slnc@textpos{\number\@tempdima}% +%<*trace> + \PackageInfo{scrlayer-notecolumn}{% + Top position is \slnc@textpos% + }% +%</trace> + \fi + \ifnum\slnc@notepos>\slnc@textpos\relax + \PackageInfo{scrlayer-notecolumn}{% + Last note position before last text\MessageBreak + position.\MessageBreak + Need rerun to sync position% + }% + \else + \ifnum\slnc@notepos<\slnc@textpos\relax + \@tempdima=\numexpr \slnc@textpos-\slnc@notepos\relax sp + \PackageInfo{scrlayer-notecolumn}{% + skipping \the\@tempdima\space to sync% + }% + \vskip\@tempdima + \fi + \fi + \fi + }% + }% + \endgroup +} +% \end{macrocode} +% \end{counter} +% \begin{macro}{\slnc@vadjust} +% \begin{macrocode} +\newcommand{\slnc@vadjust}[1]{% + \@bsphack + \vadjust{#1}% + \@esphack +} +%</body> +% \end{macrocode} +% \end{macro}^^A \slnc@vadjust +% \end{command}^^A \syncwithnotecolumn,\syncwithnotecolumns +% +% +% \begin{macrocode} +%</interface> +% \end{macrocode} +% +% \Finale +% \PrintChanges +% +\endinput +% Local Variables: +% mode: doctex +% ispell-local-dictionary: "en_US" +% eval: (flyspell-mode 1) +% TeX-master: t +% TeX-engine: luatex-dev +% eval: (setcar (or (cl-member "Index" (setq-local TeX-command-list (copy-alist TeX-command-list)) :key #'car :test #'string-equal) (setq-local TeX-command-list (cons nil TeX-command-list))) '("Index" "mkindex %s" TeX-run-index nil t :help "makeindex for dtx")) +% End: |