From 16f68bbec3cca735a695904227872abc2ace1f90 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sun, 4 Feb 2024 03:00:55 +0000 Subject: CTAN sync 202402040300 --- macros/latex/contrib/exesheet/README.md | 17 +- macros/latex/contrib/exesheet/exesheet.dtx | 169 +-- macros/latex/contrib/exesheet/exesheet.ins | 4 +- macros/latex/contrib/exesheet/exesheet.pdf | Bin 330415 -> 334627 bytes macros/latex/contrib/hvqrurl/Changes | 1 + macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf | Bin 113856 -> 115679 bytes macros/latex/contrib/hvqrurl/doc/hvqrurl.tex | 10 +- macros/latex/contrib/hvqrurl/latex/hvqrurl.sty | 17 +- macros/latex/contrib/projlib/ProjLib.dtx | 84 +- macros/latex/contrib/projlib/ProjLib.ins | 4 +- macros/latex/contrib/projlib/README.md | 8 +- .../latex/contrib/randexam/randexam-a-answer.pdf | Bin 49496 -> 49588 bytes .../latex/contrib/randexam/randexam-a-answer.tex | 8 +- macros/latex/contrib/randexam/randexam-a-blank.pdf | Bin 41288 -> 41374 bytes .../latex/contrib/randexam/randexam-b-answer.pdf | Bin 49469 -> 49570 bytes macros/latex/contrib/randexam/randexam-b-blank.pdf | Bin 41229 -> 41309 bytes macros/latex/contrib/randexam/randexam.cls | 1131 ++++++++++++-------- macros/latex/contrib/randexam/randexam.pdf | Bin 50412 -> 52431 bytes macros/latex/contrib/randexam/randexam.tex | 102 +- macros/latex/contrib/tagpdf/README.md | 4 +- macros/latex/contrib/tagpdf/ex-AF-file.pdf | 56 +- macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf | Bin 34295 -> 34295 bytes macros/latex/contrib/tagpdf/ex-attribute.pdf | 14 +- macros/latex/contrib/tagpdf/ex-formula-problem.pdf | 14 +- macros/latex/contrib/tagpdf/ex-list.pdf | 14 +- .../tagpdf/ex-mc-manual-para-split-obsolete.pdf | 14 +- macros/latex/contrib/tagpdf/ex-softhyphen.pdf | 14 +- .../contrib/tagpdf/ex-spaceglyph-listings.pdf | 14 +- .../latex/contrib/tagpdf/ex-structure-obsolete.pdf | 14 +- macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf | 50 +- macros/latex/contrib/tagpdf/tagpdf-backend.dtx | 8 +- macros/latex/contrib/tagpdf/tagpdf-checks.dtx | 4 +- macros/latex/contrib/tagpdf/tagpdf-code.pdf | Bin 1662036 -> 1673023 bytes macros/latex/contrib/tagpdf/tagpdf-data.dtx | 18 +- macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx | 6 +- macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx | 6 +- macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx | 4 +- macros/latex/contrib/tagpdf/tagpdf-roles.dtx | 4 +- macros/latex/contrib/tagpdf/tagpdf-space.dtx | 4 +- macros/latex/contrib/tagpdf/tagpdf-struct.dtx | 6 +- macros/latex/contrib/tagpdf/tagpdf-tree.dtx | 4 +- macros/latex/contrib/tagpdf/tagpdf-user.dtx | 191 ++-- macros/latex/contrib/tagpdf/tagpdf.dtx | 6 +- macros/latex/contrib/tagpdf/tagpdf.pdf | Bin 1095221 -> 1103561 bytes macros/latex/contrib/tagpdf/tagpdf.tex | 4 +- macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty | 2 +- macros/latex/contrib/wargame/README.md | 2 +- macros/latex/contrib/wargame/doc/compat.pdf | Bin 432819 -> 435053 bytes macros/latex/contrib/wargame/doc/symbols.pdf | Bin 184525 -> 186882 bytes .../latex/contrib/wargame/doc/tutorial/export.tex | 14 +- macros/latex/contrib/wargame/doc/tutorial/game.pdf | Bin 588181 -> 590545 bytes macros/latex/contrib/wargame/doc/wargame.pdf | Bin 1444437 -> 1469771 bytes macros/latex/contrib/wargame/source/Makefile | 2 +- .../latex/contrib/wargame/source/chit/battle.dtx | 2 +- macros/latex/contrib/wargame/source/chit/misc.dtx | 52 + .../contrib/wargame/source/chit/modifiers.dtx | 2 +- macros/latex/contrib/wargame/source/chit/oob.dtx | 197 +++- macros/latex/contrib/wargame/source/chit/shape.dtx | 13 +- macros/latex/contrib/wargame/source/chit/table.dtx | 58 +- macros/latex/contrib/wargame/source/hex/labels.dtx | 2 +- macros/latex/contrib/wargame/source/hex/ridges.dtx | 5 +- .../latex/contrib/wargame/source/hex/terrain.dtx | 24 +- .../latex/contrib/wargame/source/tests/chits.dtx | 14 +- macros/latex/contrib/wargame/source/tests/test.tex | 13 +- .../latex/contrib/wargame/source/util/export.dtx | 216 +++- macros/latex/contrib/wargame/source/util/tikz.dtx | 17 +- .../latex/contrib/wargame/source/utils/wgexport.py | 971 ++++++++++++++--- 67 files changed, 2585 insertions(+), 1049 deletions(-) (limited to 'macros/latex/contrib') diff --git a/macros/latex/contrib/exesheet/README.md b/macros/latex/contrib/exesheet/README.md index 6ce9032857..1c56562c44 100644 --- a/macros/latex/contrib/exesheet/README.md +++ b/macros/latex/contrib/exesheet/README.md @@ -3,14 +3,19 @@ ## Presentation -The exesheet package is designed for typesetting exercise or exam sheets. -Additionally, the exesheet class loads the schooldocs package. - -This package offers the following features: +The exesheet package is designed for typesetting exercise or exam sheets. +The primary advantage of exesheet is its ability to display +a detailed scoring guide and correction instructions as needed. +This feature is especially beneficial for grading papers with multiple graders. + +Additionally, the exesheet class loads the schooldocs package +which manages the page layout, the main title, headers and footers. + +The exesheet package offers the following features: - macros for organizing exercises and subparts, - specific settings for enumeration lists, -- environments for questions and answers, with conditional display, -- macros to display a marking scheme with detailed comments in the margins. +- environments for questions and answers, which can be displayed or hidden, +- macros for detailed comments and grading instructions in the margins which can be displayed or hidden. ## Installation diff --git a/macros/latex/contrib/exesheet/exesheet.dtx b/macros/latex/contrib/exesheet/exesheet.dtx index efc56a4cf9..02a8f5e68c 100644 --- a/macros/latex/contrib/exesheet/exesheet.dtx +++ b/macros/latex/contrib/exesheet/exesheet.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2020-2023 by Antoine Missier +% Copyright (C) 2020-2024 by Antoine Missier % ---------------------------------------------------------------------- % % This file may be distributed and/or modified under the @@ -23,7 +23,7 @@ %\ProvidesClass{exesheet} %\ProvidesPackage{exesheet} %<*class|package> -[2023/12/30 v2.5 .dtx Typesetting exercise or exam sheets] +[2024/02/03 v2.6 .dtx Typesetting exercise or exam sheets] % %<*driver> \documentclass{ltxdoc} @@ -45,6 +45,7 @@ \usepackage{pstricks} \usepackage{array} \usepackage{spacingtricks} +\usepackage{pifont} % \psset{unit=1cm} \geometry{textwidth=355pt,vmarginratio=1:1,hmarginratio=3:2} @@ -84,7 +85,7 @@ % % \fi % -% \CheckSum{1183} +% \CheckSum{1192} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -173,6 +174,10 @@ % - comparison with other packages % - modifying introduction} % +% \changes{v2.6}{2024/02/03}{ +% - error message when using colsenum or colsitem without loading multicol +% - changes in the comparison with other packages} +% % \GetFileInfo{exesheet.dtx} % % \maketitle @@ -182,7 +187,8 @@ % \section{Introduction} % % The \textsf{exesheet} \emph{package} is designed for typesetting exercise or exam sheets. -% Additionally, the \textsf{exesheet} \emph{class} loads the \textsf{schooldocs} package. +% Additionally, the \textsf{exesheet} \emph{class} loads the +% \textsf{schooldocs} package~\cite{SCHOOL}. % The latter makes adjustments to margins and titles, and defines various layout styles % with specific headers and footers suitable for exercise sheets, among other uses. % Refer to the documentation of the \textsf{schooldocs} package for more details. @@ -256,9 +262,6 @@ % Calculate $1+1$. % % \bigskip -% ^^A Various settings can be modified by refining the following commands. -% -% ^^A \medskip % \DescribeMacro{\exercisename} % The term ``\exercisename'' is automatically translated into various languages % \footnote{Currently, translation is integrated into the package @@ -314,7 +317,6 @@ % To begin, prepare your cup of tea. % \subpart % Now you are ready to proceed with the current exercise. -% \bigskip % % \pagebreak % The following macros allow customization in the same manner as for |\exercise|. @@ -589,8 +591,8 @@ % The mandatory parameter is the number of columns, % and the optional parameter will be passed to the underlying \texttt{enumerate} environment, % allowing you to change the numbering type (\eg a, A, etc.), among other possibilities. -% To use this environment, you need to load the -% \textsf{multicol} package in the preamble. +% \emph{To use this environment, you need to load the +% \textsf{multicol} package in the preamble.} % Here's an example with |\begin{colsenum}{3}|: % % \exercise @@ -643,9 +645,10 @@ % \texttt{tablitem}. It follows the same syntax as \texttt{colsenum}: % |\begin{colsitem}|\oarg{opt}\marg{cols}. The optional parameter, % passed to the underlying \texttt{itemize} environment, -% permits the modification of the item label (bullet by default). +% allow to change the item label (bullet by default). % Furthermore, just like \texttt{colsenum*}, the \texttt{colsitem*} environment % produces column alignment from the bottom. +% \emph{The \textsf{multicol} package is also required and must be loaded in the preamble.} % % \section{Questions and solutions} % @@ -710,7 +713,8 @@ % \textsf{exframe} by Niklas Beisert, % \textsf{exam} by Philip Hirschhorn, % \textsf{answers} by Mike Piff and Joseph Wright, -% \textsf{probsoln} by Nicola Talbot, and more. +% \textsf{probsoln} by Nicola Talbot, +% \textsf{eqexam} by D. P. Story\ldots % They are briefly presented in section \ref{comparison}. % \end{enumerate} % \end{answers} @@ -798,8 +802,8 @@ % Some teachers are accustomed to providing their students with documents % where questions are typeset, leaving blank spaces instead of answers. % This layout allows students to fill in their responses on the paper. -% To achieve this, thanks to a suggestion from Maxime Chupin, -% we offer the |\answerspace|\marg{height} macro, +% Thanks to a suggestion from Maxime Chupin, +% we achieve this with the |\answerspace|\marg{height} macro, % in which the parameter \meta{height} is a valid length, % \eg |\answerspace{3cm}|. % @@ -1184,7 +1188,7 @@ % answerspace & true, \textbf{false} & \ref{answerspace}\\ % display & \textbf{none}, pts, notes & \ref{pts}, \ref{margin} \\ % marginpos & \textbf{left} (inner), right (\textbf{outer}) & \ref{pts}, \ref{margin} \\ -% marginwidth & standard, \textbf{expand}, unset & \ref{margin} \\ +% marginwidth & standard, \textbf{expand}, unset & \ref{margin} \\ % noteragged & \textbf{left}, right, center, justify, twoside & \ref{margin} \\ % checkpts & true, \textbf{false} & \ref{scale} \\ % correct & true, \textbf{false}, conditional & \hyperlink{correct}{see below} \\ @@ -1225,11 +1229,10 @@ % % Prior to version 2.0, we used specialized commands to configure % output and display options. -% Thanks to a suggestion from Maxime Chupin and Denis Bitouzé, -% we have now implemented \emph{key=value} options. -% Although the latter is more user-friendly, +% We have now implemented \emph{key=value} options. +% Although the latter are more user-friendly, % one may prefer the old commands, so they are still supported, -% but will trigger a warning message. They are presented below. +% but will trigger a warning message. These commands are presented below. % % However, the previous options \texttt{nosetlist} and \texttt{notoc} % are no longer supported. @@ -1243,12 +1246,12 @@ % The commands |\displaypts| and |\displaypoints| % are equivalent to setting \texttt{display=pts}. % -% \medskip +% \bigskip % \DescribeMacro{\displaynotes}\DescribeMacro{\displaynotesright} % |\displaynotes| means \texttt{display=notes}, % and |\displaynotesright| corresponds to % \texttt{display=notes,marginpos=right}. -% These two commands have an optional argument |\displanotes|\marg{ragged} +% These two commands have an optional argument |\displaynotes|\marg{ragged} % where \meta{ragged} is an alignment command to work inside margin notes. % By default it is |\RaggedLeft| with |\displaynotes| and |RaggedRight| % \footnote{These commands come from the \textsf{ragged2e} package @@ -1258,19 +1261,19 @@ % \subsection{Comparison with other packages}\label{comparison} % % In this section, we will provide an overview of the functionalities (as of today \today) -% of various packages or classes found in the 'Exercise' or 'Exam' sections +% of various packages or classes found in the `Exercise' or `Exam' sections % of the CTAN archives % (Comprehensive \TeX\ Archive Network). % Considering the substantial number of packages in these sections, % some omissions may have been unintentionally made. % Those excluded are those with documentation not in English % or primarily dedicated to producing multiple-choice questions -% or random question generation. Are also excluded those with non-free license. -% We have focused here on typesetting functionalities and not on managing exercise databases -% as there are specialized packages or external softwares for that. +% or random question generation. +% We have focused here on typesetting functionalities and not on managing exercise +% databases as there are specialized packages or external softwares for that. % % The following table is not a result of tests but presents a summary of information -% obtained from the documentation of these packages. +% collected from the documentation of these packages. % % \begin{multicols}{2} % \begin{flushleft} @@ -1279,42 +1282,44 @@ % \item \textsf{exercises}, Roger Jud~\cite{EXES} % \item \textsf{xsim}, Clemens Niederberger~\cite{XSIM} % \item \textsf{exframe}, Niklas Beisert~\cite{EXFR} -% \item \textsf{exam}, Philip Hirschhorn~\cite{EXAM}. +% \item \textsf{exam}, Philip Hirschhorn~\cite{EXAM} % \item \textsf{answers}, Mike Piff and Joseph Wright~\cite{ANSW} % \item \textsf{probsoln}, Nicola L.C.\@ Talbot~\cite{PROB} % \item \textsf{exsol}, Walter Daems~\cite{EXSO} % \item \textsf{exercisepoints}, Henning Kerstan~\cite{EXEP} % \item \textsf{worksheet}, Benjamin Zöllner~\cite{WORK} -% \item \textsf{exam-n}, Norman Gray, CTAN~\cite{EXAN} +% \item \textsf{exam-n}, Norman Gray~\cite{EXAN} % \item \textsf{eqexam}, D. P. Story~\cite{EQEX} % \item \textsf{cesenaexam}, Alex Pacini~\cite{CESE} +% \item \textsf{esami}, Grazia Messineo, Salvatore Vassallo~\cite{ESAMI} +% \item \textsf{randexam}, Jianrui Lyu~\cite{RAND} % \item \textsf{hideanswer}, Yukoh Kusakabe~\cite{HIDE} -% \item \textsf{mathexam}, Jan Hlavacek~\cite{MATH} +% ^^A\item \textsf{mathexam}, Jan Hlavacek~\cite{MATH} % \item \textsf{exesheet}, Antoine Missier % \end{enumerate} % \end{flushleft} % \end{multicols} % -% \newcommand\X{\textsf{X}} +% \newcommand\X{\ding{56}} % \setlength{\extrarowheight}{2pt} -% \noindent\begin{tabular}{|@{\hspace{2pt}}l@{\hspace{4pt}}|% -% *{16}{@{\hspace{2pt}}c@{\hspace{2pt}}|}} +% \noindent\begin{tabular}{@{\hspace{1.8pt}}l@{\hspace{2pt}}|% +% *{17}{@{\hspace{1.8pt}}c@{\hspace{1.8pt}}|}} % \hline -% Functionality &A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P \\ +% Functionality &A&B&C&D&E&F&G&H&I&J&K&L&M&N&O&P&Q \\ % \hline -% optional text for exercise titles &\X&&\X&\X&\X&&&&\X&&&&&&&\X \\ -% subparts of exercises &\X&&&\X&\X&&&&&&\X&&\X&&&\X \\ -% annex title &&&&&&&&&&&&&&&&\X \\ -% exercise titles in TOC of PDF files &\X&&&&&&&&&&&&&&&\X \\ -% short labels for exercises &\X&&&&&&&&&&&&&&&\X \\ -% hiding questions or answers* &\X&*&\X&\X&\X&*&\X&\X&&&*&\X&&*&&\X \\ -% different placements for answers &\X&&\X&&&&&&&&&\X&&&&\X \\ -% changing answers placement in output &\X&&\X&\X&&\X&&&&&&\X&&&& \\ -% blank spacing in place of answers &&&&&\X&&&&&&&\X&&&\X&\X \\ -% marking scheme commands &&\X&\X&\X&\X&&&&\X&\X&\X&\X&&&&\X \\ -% various positions of points &&&&&\X&&&&&&&\X&&&&\X \\ -% marking scheme calculation/checking &&\X&\X&\X&\X&&&&\X&&&&&&&\X \\ -% detailed notes for scoring guide &&&&&&&&&&&&&&&&\X \\ +% Optional text for exercise titles &\X&&\X&\X&\X&&&&\X&&&&\X&&&&\X \\ +% Subparts of exercises &\X&&&\X&\X&&&&\X&&\X&\X&\X&\X&\X&&\X \\ +% Annex title or appendix &&&&&&&&&&&&&&&\X&&\X \\ +% Exercise titles in TOC of PDF files &\X&&&&&&&&&&&&&&&&\X \\ +% Short labels for exercises &\X&&\X&\X&&&&&&&&&&&&&\X \\ +% Hiding questions or answers* &\X&*&\X&\X&*&\X&\X&\X&&&*&\X&&\X&*&*&\X \\ +% Different placements for answers &\X&&&&&&&&&&\X&\X&&&&&\X \\ +% Change answers placement in output &\X&&&\X&&\X&&\X&&&&\X&&&&& \\ +% Blank spacing in place of answers &&\X&\X&&\X&&&&&&&\X&&\X&\X&&\X \\ +% Marking scheme commands &&\X&\X&\X&\X&&&&\X&\X&\X&\X&&\X&\X&&\X \\ +% Various positions of points &&&&\X&\X&&&&&&&\X&&\X&&&\X \\ +% Marking scheme calculation/checking &&\X&\X&\X&\X&&&&\X&&\X&\X&&&\X&&\X \\ +% Detailed notes for scoring guide &&&&&&&&&&&&&&&&&\X \\ % \hline % \end{tabular} % \medskip @@ -1802,11 +1807,20 @@ \end{tablitem}} % \end{macrocode} -% \DescribeEnv{colsenum} +% \DescribeEnv{colsenum}\DescribeEnv{colsenum*} +% For items aligned by columns, we provide the \texttt{colsemnum} and \texttt{colsenum*} +% environments. The \textsf{multicol} package is required and an error message +% is produced if it has not been loaded. +% |\multicolsep| is the amount of space that should be added above or below the +% environment. % \begin{macrocode} -\newenvironment{colsenum}[2][]{% +\newenvironment{colsenum*}[2][]{% + \ifexesheet@multicol \else + \PackageError{exesheet}{The environments colsenum and colsenum* + \MessageBreak need the multicol package}{ + Add \string\usepackage{multicol}\space in the preamble.} + \fi \setlength{\multicolsep}{2ex} - \raggedcolumns % default is \flushcolumns \begin{multicols}{#2} % #2 = number of columns \begin{enumerate}[#1] % #1 = options of enumerate }{ @@ -1814,41 +1828,36 @@ \end{multicols} } -% \end{macrocode} -% \DescribeEnv{colsenum*} -% \begin{macrocode} -\newenvironment{colsenum*}[2][]{% - \setlength{\multicolsep}{2ex} - \begin{multicols}{#2} % #2 = number of columns - \begin{enumerate}[#1] % #1 = options of enumerate +\newenvironment{colsenum}[2][]{% + \raggedcolumns % default is \flushcolumns + \begin{colsenum*}[#1]{#2} }{ - \end{enumerate} - \end{multicols} + \end{colsenum*} } % \end{macrocode} -% \DescribeEnv{colsitem} +% \DescribeEnv{colsitem}\DescribeEnv{colsitem*} +% The corresponding environments for itemize lists. % \begin{macrocode} -\newenvironment{colsitem}[2][]{% +\newenvironment{colsitem*}[2][]{% + \ifexesheet@multicol \else + \PackageError{exesheet}{The environments colsitem and colsitem* + \MessageBreak need the multicol package}{ + Add \string\usepackage{multicol}\space in the preamble.} + \fi \setlength{\multicolsep}{2ex} - \raggedcolumns - \begin{multicols}{#2} - \begin{itemize}[#1] + \begin{multicols}{#2} % #2 = number of columns + \begin{itemize}[#1] % #1 = options of itemize }{ \end{itemize} \end{multicols} } -% \end{macrocode} -% \DescribeEnv{colsitem*} -% \begin{macrocode} -\newenvironment{colsitem*}[2][]{% - \setlength{\multicolsep}{2ex} - \begin{multicols}{#2} - \begin{itemize}[#1] +\newenvironment{colsitem}[2][]{% + \raggedcolumns % default is \flushcolumns + \begin{colsitem*}[#1]{#2} }{ - \end{itemize} - \end{multicols} + \end{colsitem*} } % \end{macrocode} @@ -2024,8 +2033,8 @@ % \end{macrocode} % % \begin{macro}{\answerspace} -% The |\answerspace| macro was suggested by Maxime Chupin -% to allow students space for writing their answers on the provided paper. +% The |\answerspace| macro leaves blank space to allow students for writing +% their answers on the provided paper following a suggestion by Maxime Chupin. % \begin{macrocode} \newcommand\answerspace[1]{ \ifexesheet@answerspace \par\vspace{#1} \fi} @@ -2563,11 +2572,13 @@ % \end{macrocode} % \end{macro} % -% \begin{thebibliography}{24} +% \begin{thebibliography}{27} % % \begin{raggedright} +% \bibitem{SCHOOL} \emph{The \textsf{schooldocs} package}, Antoine Missier, +% CTAN, v1.4 2023/12/28. % \bibitem{GEOM} \emph{The \textsf{geometry} package}, % Hideo Umeki, CTAN, v5.9 2020/01/02. -% \bibitem{ENUM} \emph{Customizing lists with teh \textsf{enumitem} package}, +% \bibitem{ENUM} \emph{Customizing lists with the \textsf{enumitem} package}, % Javier Bezos, CTAN, v3.9 2019/06/20. % \bibitem{TASK} \emph{\textsf{tasks} -- lists with columns filled horizontally}, % Clemens Niederberger. CTAN, v1.4a, 2022/01/08. @@ -2591,7 +2602,7 @@ % the official successor of the \textsf{exsheets} package}, Clemens Niederberger, % CTAN, v0.21 2022/02/12. % \bibitem{EXFR} \emph{The \textsf{exframe} package}, Niklas Beisert, -% CTAN, v3.4 202/02/24. +% CTAN, v3.4 2020/02/24. % \bibitem{EXAM} \emph{Using the \textsf{exam} document class}, Philip Hirschhorn, % CTAN, v2.704 2023/07/09. % \bibitem{ANSW} \emph{\textsf{answers} Production of solution sheets in \LaTeXe}, @@ -2608,6 +2619,10 @@ % D. P. Story, CTAN, 5.2 2021/02/26. % \bibitem{CESE} \emph{\textsf{cesenaexam} — class file to typeset exams}, Alex Pacini, % CTAN, v2.0 2017/08/03. +% \bibitem{ESAMI} \emph{Package \textsf{esami}}, Grazia Messineo, Salvatore Vassallo, +% CTAN, v2.8 2023/07/21. +% \bibitem{RAND} \emph{Teh \textsf{randexam} class for \LaTeX}, Jianrui Lyu, +% CTAN, 2024D, 2024/02/03. % \bibitem{HIDE} \emph{The \textsf{hideanswer} package: generate documents with % and without answers by toggling a switch}, Yukoh Kusakabe, CTAN, v1.1 2022/07/09. % \bibitem{MATH} \emph{The \textsf{mathexam} Package}, Jan Hlavacek, CTAN, v1.00 2007/07/30. diff --git a/macros/latex/contrib/exesheet/exesheet.ins b/macros/latex/contrib/exesheet/exesheet.ins index 4784c5b955..d1fc87865f 100644 --- a/macros/latex/contrib/exesheet/exesheet.ins +++ b/macros/latex/contrib/exesheet/exesheet.ins @@ -1,5 +1,5 @@ %% -%% Copyright (C) 2020-2023 by Antoine Missier +%% Copyright (C) 2020-2024 by Antoine Missier %% %% This file may be distributed and/or modified under the conditions of %% the LaTeX Project Public License, either version 1.3 of this license @@ -21,7 +21,7 @@ This is a generated file. -Copyright (C) 2020-2023 by Antoine Missier +Copyright (C) 2020-2024 by Antoine Missier This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license diff --git a/macros/latex/contrib/exesheet/exesheet.pdf b/macros/latex/contrib/exesheet/exesheet.pdf index be92d96cc5..b18f1858e7 100644 Binary files a/macros/latex/contrib/exesheet/exesheet.pdf and b/macros/latex/contrib/exesheet/exesheet.pdf differ diff --git a/macros/latex/contrib/hvqrurl/Changes b/macros/latex/contrib/hvqrurl/Changes index a14d35f255..e7b6ca476c 100644 --- a/macros/latex/contrib/hvqrurl/Changes +++ b/macros/latex/contrib/hvqrurl/Changes @@ -1,4 +1,5 @@ hvqrurl.sty: +0.06 2024-02-03 - fix for introduced bug with linktext 0.05a 2024-02-02 - modified documentation 0.05 2024-01-28 - added optional argument for alternative link text 0.04 2024-01-18 - fix for wrong text diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf index 0ea564f2d7..b5103b9d16 100644 Binary files a/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf and b/macros/latex/contrib/hvqrurl/doc/hvqrurl.pdf differ diff --git a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex index 5b0e10dc06..79c2c395ea 100644 --- a/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex +++ b/macros/latex/contrib/hvqrurl/doc/hvqrurl.tex @@ -1,4 +1,4 @@ -%% $Id: hvqrurl.tex 867 2024-02-02 09:03:16Z herbert $ +%% $Id: hvqrurl.tex 870 2024-02-03 20:38:44Z herbert $ \listfiles \errorcontextlines=100 \documentclass[twoside=on,usegeometry]{scrartcl} @@ -82,6 +82,8 @@ QR codes not as a link when using \LPack{hyperref}: \subsection{No link with \LPack{hyperref}} +This needs package hyperref, which is loaded by default. With the optional argument +\Lkeyword{nohyperref} you can prevent the loading of this package. \begin{lstlisting} With qrlink=nolink the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}. @@ -89,7 +91,11 @@ The default setting is qrlink=link. \end{lstlisting} With \Lkeyset{qrlink=nolink} the QR code is no link: \hvqrurl[qrlink=nolink]{https://mirror.ctan.org/pkg/hvqrurl}. The default setting is \Lkeyset{qrlink=link}. Without using \LPack{hyperref} this optional argument -has no meaning. +has no meaning. The optional argument \Lkeyword{linktext} is also only valid, if hyperref is aktive. + + + + \subsection{Color of the QR code} Without using \LPack{hyperref} the default color is \Lkeyval{black}. It can be changed by diff --git a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty index 9786732d94..36f90a2638 100644 --- a/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty +++ b/macros/latex/contrib/hvqrurl/latex/hvqrurl.sty @@ -1,4 +1,4 @@ -%% $Id: hvqrurl.sty 867 2024-02-02 09:03:16Z herbert $ +%% $Id: hvqrurl.sty 870 2024-02-03 20:38:44Z herbert $ %% %% This file is distributed under the terms of the LaTeX Project Public %% License from CTAN archives in directory macros/latex/base/lppl.txt. @@ -7,7 +7,7 @@ % Copyright 2019,21,23,24 Herbert Voss hvoss@tug.org %% \ProvidesPackage{hvqrurl}[% - 2024/02/02 v.0.05a (Herbert Voss) Supports qr images into the margin (hv)] + 2024/02/03 v.0.06 (Herbert Voss) Supports qr images into the margin (hv)] % \NeedsTeXFormat{LaTeX2e} \RequirePackage{url} @@ -16,6 +16,12 @@ \RequirePackage{qrcode} \RequirePackage{xkeyval} +\newif\if@no@hyperref \@no@hyperreffalse +\DeclareOption{nohyperref}{\@no@hyperreftrue} +\ProcessOptions + +\if@no@hyperref\else\RequirePackage{hyperref}\fi + \newlength\qr@url@qrheight \newlength\qr@url@qradjust @@ -36,19 +42,22 @@ \def\hvqr@url*{\hvqr@@url} + \newcommand*\hvqr@@url[2][]{% \begingroup \providecommand*\qr@blank{0}% \ifx\relax#1\relax \else\hvqrset{#1}\fi + % Set options for package qrcode \expandafter\qrset\expandafter{\qr@url@qrlink,height=\qr@url@qrheight,level=\qr@url@qrlevel}% \ifhv@qrreverse\reversemarginpar\fi \if@tempswa - \ifx\relax\qr@url@linktext\relax % alternative link text?? + \ifx\@empty\qr@url@linktext % alternative link text \edef\hv@foo{\detokenize\expandafter{#2}}% + \url{\hv@foo}% \else \edef\hv@foo{\detokenize\expandafter{\qr@url@linktext}}% + \href{#2}{\hv@foo}% \fi - \expandafter\url\expandafter{\hv@foo}% \fi \edef\reserved@a{\noexpand\marginnote{\noexpand\color{qr@url@qrcolor}\noexpand\qrcode{% \detokenize\expandafter{#2}}}[\qr@url@qradjust]}% diff --git a/macros/latex/contrib/projlib/ProjLib.dtx b/macros/latex/contrib/projlib/ProjLib.dtx index fcac850e84..1172d3e4ad 100644 --- a/macros/latex/contrib/projlib/ProjLib.dtx +++ b/macros/latex/contrib/projlib/ProjLib.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2021-2023 by Jinwen XU +% Copyright (C) 2021-2024 by Jinwen XU % ------------------------------------ % % This file may be distributed and/or modified under the conditions of the LaTeX @@ -19,85 +19,85 @@ %<*ProjLib> \ProvidesExplPackage {ProjLib} - {2023/11/05} {} + {2024/02/03} {} {Collective interface of the ProjLib toolkit} % % %<*projlib-author> \ProvidesExplPackage {projlib-author} - {2023/11/05} {} + {2024/02/03} {} {Enhanced author information block} % % %<*projlib-datetime> \ProvidesExplPackage {projlib-datetime} - {2023/11/05} {} + {2024/02/03} {} {Convert numeric date-time string to natural language} % % %<*projlib-draft> \ProvidesExplPackage {projlib-draft} - {2023/11/05} {} + {2024/02/03} {} {Useful commands during draft stage} % % %<*projlib-font> \ProvidesExplPackage {projlib-font} - {2023/11/05} {} + {2024/02/03} {} {Font selection and configuration} % % %<*projlib-language> \ProvidesExplPackage {projlib-language} - {2023/11/05} {} + {2024/02/03} {} {Multi-language configuration} % % %<*projlib-logo> \ProvidesExplPackage {projlib-logo} - {2023/11/05} {} + {2024/02/03} {} {The ProjLib logo} % % %<*projlib-math> \ProvidesExplPackage {projlib-math} - {2023/11/05} {} + {2024/02/03} {} {Efficient math setup} % % %<*projlib-paper> \ProvidesExplPackage {projlib-paper} - {2023/11/05} {} + {2024/02/03} {} {Configuration of the paper style} % % %<*projlib-text> \ProvidesExplPackage {projlib-text} - {2023/11/05} {} + {2024/02/03} {} {Text-related commands} % % %<*projlib-theorem> \ProvidesExplPackage {projlib-theorem} - {2023/11/05} {} + {2024/02/03} {} {Configuration of theorem-like environments} % % %<*projlib-titlepage> \ProvidesExplPackage {projlib-titlepage} - {2023/11/05} {} - {Commands for rendering the title page} + {2024/02/03} {} + {Interface for title page rendering} % %<*ProjLib> @@ -5521,9 +5521,12 @@ \tl_set_eq:NN \thepage \l_projlib_titlepage_license_page_name_tl \thispagestyle{empty} \null\vfill - \begin{flushleft} + % \begin{flushleft} + \group_begin: + \noindent \tl_use:N \l_projlib_titlepage_info_tl - \end{flushleft} + \group_end: + % \end{flushleft} \group_begin: \tl_use:N \l_projlib_titlepage_license_tl \group_end: @@ -5532,38 +5535,37 @@ \pagenumbering{roman} } + \cs_new_protected:Nn \projlib_titlepage_render_with_style_default: { \begin{tikzpicture}[overlay,remember~picture] - \fill [color=titlepage-main] ($(current~page.south~west)$) rectangle ($(current~page.north~east)+(0,-.3\paperheight)$); - \fill [color=titlepage-back] ($(current~page.south~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); - \fill [color=titlepage-main] ($(current~page.north~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); - \fill [color=titlepage-back] ($(current~page.north~east)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); + % \fill[color=white] ($(current~page.south~west)$) rectangle ($(current~page.north~east)$); \node[text~width=.3\paperwidth, text~height=.2\paperheight, align=flush~left] - at ($(current~page.north~west)+(.333\paperwidth,-.17\paperheight)$) + at ($(current~page.north~west)+(.32\paperwidth,-.1\paperheight)$) { \projlib_titlepage_show_logo:n { \scalebox { 2 } { \ProjLib } } }; \node[text~width=.8\paperwidth, text~height=.5\paperheight, align=flush~left] - at ($(current~page.north~west)+(.583\paperwidth,-.28\paperheight)$) + at ($(current~page.north~west)+(.57\paperwidth,-.15\paperheight)$) { - \color{titlepage-back} \sffamily \fontsize{24pt}{36pt}\selectfont - \textsc{ \l_projlib_titlepage_title_tl }\\[1.5em] + \textsc{ \textbf{ \l_projlib_titlepage_title_tl } }\\[1.5em] \fontsize{18pt}{27pt}\selectfont \l_projlib_titlepage_subtitle_tl }; - \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left] - at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$) + % \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left] + % at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$) + \node[text~width=.8\paperwidth, text~height=.4\paperheight, align=flush~left] + at ($(current~page.south~west)+(.57\paperwidth,.45\paperheight)$) { - \color{titlepage-back} - \begin{flushright} + % \color{.!50} + % \begin{flushright} \fontsize{16pt}{24pt}\selectfont \textsc{ \l_projlib_titlepage_author_tl }\\[1em] \fontsize{12pt}{18pt}\selectfont \l_projlib_titlepage_date_tl - \end{flushright} + % \end{flushright} }; \end{tikzpicture} } @@ -5634,36 +5636,38 @@ \end{tikzpicture} } -\cs_new_protected:Nn \projlib_titlepage_render_with_style_minimalist: +\cs_new_protected:Nn \projlib_titlepage_render_with_style_fancy: { \begin{tikzpicture}[overlay,remember~picture] - % \fill[color=white] ($(current~page.south~west)$) rectangle ($(current~page.north~east)$); + \fill [color=titlepage-main] ($(current~page.south~west)$) rectangle ($(current~page.north~east)+(0,-.3\paperheight)$); + \fill [color=titlepage-back] ($(current~page.south~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); + \fill [color=titlepage-main] ($(current~page.north~west)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); + \fill [color=titlepage-back] ($(current~page.north~east)$) rectangle ($(current~page.north~west)+(.125\paperwidth,-.3\paperheight)$); \node[text~width=.3\paperwidth, text~height=.2\paperheight, align=flush~left] - at ($(current~page.north~west)+(.32\paperwidth,-.2\paperheight)$) + at ($(current~page.north~west)+(.333\paperwidth,-.17\paperheight)$) { \projlib_titlepage_show_logo:n { \scalebox { 2 } { \ProjLib } } }; \node[text~width=.8\paperwidth, text~height=.5\paperheight, align=flush~left] - at ($(current~page.north~west)+(.57\paperwidth,-.22\paperheight)$) + at ($(current~page.north~west)+(.583\paperwidth,-.28\paperheight)$) { + \color{titlepage-back} \sffamily \fontsize{24pt}{36pt}\selectfont \textsc{ \l_projlib_titlepage_title_tl }\\[1.5em] \fontsize{18pt}{27pt}\selectfont \l_projlib_titlepage_subtitle_tl }; - % \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left] - % at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$) - \node[text~width=.8\paperwidth, text~height=.4\paperheight, align=flush~left] - at ($(current~page.south~west)+(.57\paperwidth,.45\paperheight)$) + \node[text~width=.5\paperwidth, text~height=.4\paperheight, align=flush~left] + at ($(current~page.south)+(.135\paperwidth,.35\paperheight)$) { - \color{.!50} - % \begin{flushright} + \color{titlepage-back} + \begin{flushright} \fontsize{16pt}{24pt}\selectfont \textsc{ \l_projlib_titlepage_author_tl }\\[1em] \fontsize{12pt}{18pt}\selectfont \l_projlib_titlepage_date_tl - % \end{flushright} + \end{flushright} }; \end{tikzpicture} } diff --git a/macros/latex/contrib/projlib/ProjLib.ins b/macros/latex/contrib/projlib/ProjLib.ins index 19afe26f96..67c129761e 100644 --- a/macros/latex/contrib/projlib/ProjLib.ins +++ b/macros/latex/contrib/projlib/ProjLib.ins @@ -1,5 +1,5 @@ %% -%% Copyright (C) 2021-2023 by Jinwen XU +%% Copyright (C) 2021-2024 by Jinwen XU %% %% This file may be distributed and/or modified under the conditions of %% the LaTeX Project Public License, either version 1.3c of this license @@ -20,7 +20,7 @@ \ds@heading% This is file... generated with the docstrip utility. \MetaPrefix% -Copyright (C) 2021-2023 by Jinwen XU +Copyright (C) 2021-2024 by Jinwen XU This is part of the ProjLib Toolkit. }% diff --git a/macros/latex/contrib/projlib/README.md b/macros/latex/contrib/projlib/README.md index b9b4816d75..f7f7c70dbe 100644 --- a/macros/latex/contrib/projlib/README.md +++ b/macros/latex/contrib/projlib/README.md @@ -1,11 +1,11 @@ - +
# The `ProjLib` Toolkit -> **This bundle is dated 2023/11/05.** +> **This bundle is dated 2024/02/03.** > **New documentations are still being written. For now, only the core code is included in TeX Live 2023 (old documentations have been removed from the distribution).** @@ -63,8 +63,8 @@ The modules include: - Supporting the modes `simple name` and `complex name` for the referencing names. - `\SwitchTheoremNumbering` and `\DisableTheoremNumbering` for manipulating the numbering. - Preset environments include: `application`, `assertion`, `assumption`, `axiom`, `claim`, `conclusion`, `conjecture`, `construction`, `convention`, `corollary`, `definition`, `definition-proposition`, `definition-theorem`, `example`, `exercise`, `fact`, `hypothesis`, `lemma`, `notation`, `observation`, `postulate`, `problem`, `property`, `proposition`, `question`, `recall`, `remark`, `theorem`, and the corresponding unnumbered version with an asterisk `*` in the name. -1. module `titlepage` - *Commands for rendering the title page* - - Currently support four title page styles: `default`, `academic`, `minimalist` and `simple`. +1. module `titlepage` - *Interface for title page rendering* + - Currently support four title page styles: `default`, `academic`, `simple` and `fancy`. > Since the module `theorem` uses `cleveref`, it should be loaded after `varioref` and `hyperref` (same for the main package `ProjLib`). diff --git a/macros/latex/contrib/randexam/randexam-a-answer.pdf b/macros/latex/contrib/randexam/randexam-a-answer.pdf index d7d570e9b2..6c62155246 100644 Binary files a/macros/latex/contrib/randexam/randexam-a-answer.pdf and b/macros/latex/contrib/randexam/randexam-a-answer.pdf differ diff --git a/macros/latex/contrib/randexam/randexam-a-answer.tex b/macros/latex/contrib/randexam/randexam-a-answer.tex index fdfec30618..bd1cbc9f70 100644 --- a/macros/latex/contrib/randexam/randexam-a-answer.tex +++ b/macros/latex/contrib/randexam/randexam-a-answer.tex @@ -1,8 +1,8 @@ % -*- coding: utf-8 -*- % !TEX program = xelatex -\documentclass[12pt,most]{randexam} +\documentclass[12pt,math=all]{randexam} -%\answerfalse % hide answers +%\boolfalse{exam@answer} % hide answers \SetExamOption{ seed = 19061116, % random seed @@ -10,7 +10,7 @@ \begin{document} -\examtitle{name=Math 1906 Final Exam,date=2018-06-28,version=A} % make exam title +\examtitle{name=Math 1906 Final Exam,date=\today,version=A} % make exam title \gradetable[total=4] @@ -309,7 +309,7 @@ Text text $H_0:\mu=3140$ text text ($\alpha = 0.01$). \exampart{Work out math proofs.}{2 questions; 16 points in total.} -\DeclareExamTranslation{current}{solution-Solution=Proof} % rename "Solution" as "Proof" +\SetExamTranslation{solution-Solution=Proof} % rename "Solution" as "Proof" \begin{question}[points=9] The first question $\{x_n\}$ text $x_1=\sqrt2$, $x_{n+1}=\sqrt{2+x_n}$. diff --git a/macros/latex/contrib/randexam/randexam-a-blank.pdf b/macros/latex/contrib/randexam/randexam-a-blank.pdf index 1a85a26f4c..dcc54e2939 100644 Binary files a/macros/latex/contrib/randexam/randexam-a-blank.pdf and b/macros/latex/contrib/randexam/randexam-a-blank.pdf differ diff --git a/macros/latex/contrib/randexam/randexam-b-answer.pdf b/macros/latex/contrib/randexam/randexam-b-answer.pdf index 349d3a80d9..c6be0a3b3d 100644 Binary files a/macros/latex/contrib/randexam/randexam-b-answer.pdf and b/macros/latex/contrib/randexam/randexam-b-answer.pdf differ diff --git a/macros/latex/contrib/randexam/randexam-b-blank.pdf b/macros/latex/contrib/randexam/randexam-b-blank.pdf index 5ee6962d09..17ea5a41ab 100644 Binary files a/macros/latex/contrib/randexam/randexam-b-blank.pdf and b/macros/latex/contrib/randexam/randexam-b-blank.pdf differ diff --git a/macros/latex/contrib/randexam/randexam.cls b/macros/latex/contrib/randexam/randexam.cls index d103dfe558..105d3de168 100644 --- a/macros/latex/contrib/randexam/randexam.cls +++ b/macros/latex/contrib/randexam/randexam.cls @@ -1,50 +1,81 @@ % -*- coding: utf-8 -*- % ---------------------------------------------------------------------------- % Author: Jianrui Lyu +% Package: https://ctan.org/pkg/randexam % License: The LaTeX Project Public License 1.3c % ---------------------------------------------------------------------------- \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{randexam}[2024-01-28 v2024C Make an exam paper and its randomized variants] +\ProvidesClass{randexam}[2024-02-03 v2024D Make an exam paper and its randomized variants] %% Old LaTeX release could not recognize date format like 2022-11-01 %\@ifl@t@r\fmtversion{2022-11-01}{}{ \@ifl@t@r\fmtversion{2022/11/01}{}{ \ClassError{randexam}{% Your current TeX distribution is quite old.\MessageBreak - We need CTeX 3.0+ or MiKTeX 2023+ or TeXLive 2023+% + We need TeXLive 2023+ or MiKTeX 2023+ or CTeX 3.0+% }{Please update your TeX distribution first.} } +%% --------------------------------------------------------------------------- +%% Start ignoring spaces in the code +%% --------------------------------------------------------------------------- + \RequirePackage{functional} \IgnoreSpacesOn +%% --------------------------------------------------------------------------- +%% Declare class options +%% --------------------------------------------------------------------------- + \RequirePackage{etoolbox} -\newbool{plain} \boolfalse{plain} % use plain page style -\newbool{twoinone} \boolfalse{twoinone} % use A3 paper -\newbool{oneside} \boolfalse{oneside} % use single sided exam paper -\newbool{resetnumber} \booltrue{resetnumber} % reset numbers in new exam groups -\newbool{random} \boolfalse{random} % shuffle questions -\newbool{answer} \booltrue{answer} % show answers -\newbool{amsfonts} \boolfalse{amsfonts} % use ams fonts -\newbool{freealign} \boolfalse{freealign} % load freealign package -\newbool{medmath} \boolfalse{medmath} % use medium-size formulas -\newbool{evaluator} \boolfalse{evaluator} % add evaluator line in the grade table - -\DeclareKeys{ - plain .if = plain, - a3paper .if = twoinone, - a3input .code = \booltrue{twoinone}\booltrue{plain}, - oneside .if = oneside, - random .if = random, - noanswer .ifnot = answer, - amsfonts .if = amsfonts, - freealign .if = freealign, - medmath .if = medmath, - evaluator .if = evaluator, - many .code = \booltrue{freealign}, - most .code = \booltrue{freealign}\booltrue{medmath} +\newbool{exam@plain} \boolfalse{exam@plain} % use plain page style +\newbool{exam@twoinone} \boolfalse{exam@twoinone} % use A3 paper +\newbool{exam@oneside} \boolfalse{exam@oneside} % use single sided exam paper +\newbool{exam@resetnumber}\booltrue{exam@resetnumber} % reset numbers in new exam parts +\newbool{exam@random} \boolfalse{exam@random} % shuffle questions +\newbool{exam@answer} \booltrue{exam@answer} % show answers +\newbool{exam@evaluator} \boolfalse{exam@evaluator} % add evaluator line in the grade table +\newbool{exam@mathdesign} \booltrue{exam@mathdesign} % use mathdesign fonts +\newbool{exam@freealign} \boolfalse{exam@freealign} % load freealign package +\newbool{exam@medmath} \boolfalse{exam@medmath} % use medium-size formulas +\newbool{exam@moremath} \boolfalse{exam@moremath} % define more math commands + +\DeclareKeys[randexam]{ + plain .if = exam@plain + ,a3paper .if = exam@twoinone + ,a3input .code = \booltrue{exam@twoinone}\booltrue{exam@plain} + ,oneside .if = exam@oneside + ,random .if = exam@random + ,noanswer .ifnot = exam@answer + ,evaluator .if = exam@evaluator + ,mathdesign .if = exam@mathdesign + ,freealign .if = exam@freealign + ,medmath .if = exam@medmath + ,moremath .if = exam@moremath + ,math .choice: + ,math .default:n = many + ,math/many .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign} + ,math/most .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign} + \booltrue{exam@medmath} + ,math/all .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign} + \booltrue{exam@medmath}\booltrue{exam@moremath} +} + +%% Support for Chinese language +\newbool{exam@ctex} \boolfalse{exam@ctex} % load ctex package +\newbool{exam@solidot} \boolfalse{exam@solidot} % use full-width solid periods +\newbool{exam@sourcehan}\boolfalse{exam@sourcehan} % use source han font +\DeclareKeys[randexam]{ + ctex .if = exam@ctex + ,solidot .if = exam@solidot + ,sourcehan .if = exam@sourcehan + ,chinese .choice: + ,chinese .default:n = many + ,chinese/many .code = \booltrue{exam@ctex} + ,chinese/most .code = \booltrue{exam@ctex}\booltrue{exam@solidot} + ,chinese/all .code = \booltrue{exam@ctex}\booltrue{exam@solidot}\booltrue{exam@sourcehan} } \DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{article}} @@ -53,11 +84,11 @@ \LoadClass{article} -\iftwoinone +\ifbool{exam@twoinone}{ \RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry} -\else +}{ \RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry} -\fi +} \RequirePackage{amsmath} \RequirePackage{array} @@ -70,18 +101,26 @@ \RequirePackage{tabularx} \RequirePackage{xcolor} -\ifplain - \allowdisplaybreaks[4] -\fi +\ifbool{exam@plain}{\allowdisplaybreaks[4]}{} -\ifamsfonts - \RequirePackage{amssymb} -\else +\ifbool{exam@twoinone}{ + \RequirePackage{pdfpages} + % When pdfpages package is newer enough, putting \includepdf at the beginning + % of document body will cause an error about an undefined command; + % see https://tex.stackexchange.com/questions/352007/ieeetran-and-pdfpages + % Also since LaTeX release 2018-04-01 \@ifundefined won't turn an undefined command + % into \relax; see https://www.latex-project.org/news/latex2e-news/ltnews28.pdf + \@ifundefined{@setmarks}{\let\@setmarks\relax}{} +}{} + +\ifbool{exam@mathdesign}{ \RequirePackage[utopia]{mathdesign} % charter, utopia \renewcommand\bfdefault{bx} \let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits} \DeclareTextCommandDefault{\nobreakspace}{\leavevmode\nobreak\ } -\fi +}{ + \RequirePackage{amssymb} +} \newcolumntype{Y}{>{\centering\arraybackslash}X} \newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}} @@ -101,13 +140,11 @@ %% Otherwise, we may enable the template by using \SelectExamTemplate command \NewDocumentCommand\DeclareExamTemplate{mm+m}{ \tlSet{\expName{l@rdxm@template@#1@#2@tl}}{#3} - \ignorespaces } %% #1: exam element; #2: template name \NewDocumentCommand\SelectExamTemplate{mm}{ \tlSetEq{\expName{l@rdxm@template@#1@default@tl}}{\expName{l@rdxm@template@#1@#2@tl}} - \ignorespaces } %% #1: exam element; #2: template name. @@ -122,7 +159,7 @@ \tlSet\l@rdxm@current@language@tl{english} -\DeclareUnknownKeyHandler[randexam-translation]{ +\DeclareUnknownKeyHandler[randexam/translation]{ \tlSet{\expName{l@rdxm@translate@\l@rdxm@declare@language@tl @#1@tl}}{#2} } @@ -133,14 +170,18 @@ }{ \tlSet\l@rdxm@declare@language@tl{#1} } - \SetKeys[randexam-translation]{#2} - \ignorespaces + \SetKeys[randexam/translation]{#2} +} + +%% #1: a keyval list with keyword = transaltion format +\NewDocumentCommand\SetExamTranslation{m}{ + \tlSetEq\l@rdxm@declare@language@tl\l@rdxm@current@language@tl + \SetKeys[randexam/translation]{#1} } %% #1: language name \NewDocumentCommand\SelectExamTranslation{m}{ \tlSet\l@rdxm@current@language@tl{#1} - \ignorespaces } %% #1: keyword name. @@ -149,6 +190,17 @@ \UseName{l@rdxm@translate@\l@rdxm@current@language@tl @#1@tl} } +%% #1: keyword translation; #2: keyword number. +%% The \relax prevents functional package from treating the result as a function +\NewDocumentCommand\MakeExamNameNumber{mm}{ + \clistSet\lTmpaClist{\expWhole{#1}} + \intCompareTF{\clistVarCount\lTmpaClist}>{1}{ + \prgReturn{\relax\clistVarItem\lTmpaClist{1}#2\clistVarItem\lTmpaClist{2}} + }{ + \prgReturn{#1~#2} + } +} + \DeclareExamTranslation{english}{ answertable-Answer = Answer ,answertable-Number = Number @@ -174,21 +226,54 @@ \SelectExamTranslation{english} %% --------------------------------------------------------------------------- -%% Keyvalue commands for exam options +%% Keyvalue commands for exam elements %% --------------------------------------------------------------------------- -%% #1 module name; #2: key name; #3: its value -\NewDocumentCommand\DeclareExamValue{mm+m}{ +%% #1 element name; #2: key definitions +\NewDocumentCommand\DeclareExamValue{m+m}{ + \DeclareKeys[randexam/#1]{#2} +} + +%% #1 element name; #2: key name; #3: its value +\NewDocumentCommand\rdxm@set@one@value{mm+m}{ \tlSet{\expName{l@rdxm@value@#1@#2@tl}}{#3} - \ignorespaces } -%% #1: module name; #2: key name. +\newrobustcmd\rdxm@declare@key@handler[1]{ + \DeclareUnknownKeyHandler[randexam/#1]{\rdxm@set@one@value{#1}{##1}{##2}} +} + +%% #1 element name; #2: key-value list +\NewDocumentCommand\SetExamValue{m+m}{ + \rdxm@declare@key@handler{#1} + \SetKeys[randexam/#1]{#2} +} + +%% #1: element name; #2: key name. %% In an expandable command, we should use \UseName but not \expName. +%% When the key is undefined, the expanded result of \UseName is \relax, +%% and we could test this case with \tlIfExist function. \NewExpandableDocumentCommand\UseExamValue{mm}{ \UseName{l@rdxm@value@#1@#2@tl} } +%% In fact, \ifdef/ifcsname is a wrapper for \ifdefined/\ifcsname in eTeX; +%% they will not turn an undefined macro into \relax +\NewExpandableDocumentCommand\IfExamValueExistT{mm+m}{ + \ifcsdef{l@rdxm@value@#1@#2@tl}{#3}{} +} +\NewExpandableDocumentCommand\IfExamValueExistF{mm+m}{ + \ifcsdef{l@rdxm@value@#1@#2@tl}{}{#3} +} +\NewExpandableDocumentCommand\IfExamValueExistTF{mm+m+m}{ + \ifcsdef{l@rdxm@value@#1@#2@tl}{#3}{#4} +} + +%% #1 element name +\NewDocumentCommand\TheExamCounter{m}{ + \UseExamValue{#1}{number}{#1} +} + %% --------------------------------------------------------------------------- %% Command for exam title: \examtitle %% --------------------------------------------------------------------------- @@ -197,23 +282,14 @@ \newcommand{\underbox}[2]{\kern0pt\underline{\makebox[#1]{#2}}\kern0pt\relax} \newcommand{\underparbox}[2]{\kern0pt\underline{\parbox[b]{#1}{#2}}\kern0pt\relax} -\newcommand{\ischeck}[1]{\ifnum#1>0\,$\checkmark$\,\else\quad\fi} -\newcommand{\isquad}[1]{\ifnum#1=0\,$\checkmark$\,\else\quad\fi} - -\DeclareKeys[randexam-title]{ - name .code = \DeclareExamValue{examtitle}{name}{#1} - ,date .code = \DeclareExamValue{examtitle}{date}{#1} - ,version .code = \DeclareExamValue{examtitle}{version}{#1} -} - -\NewDocumentCommand\SetExamTitle{+m}{\SetKeys[randexam-title]{#1}} +\rdxm@declare@key@handler{examtitle} -\SetExamTitle{name=Math~1906,date=\today,version=A} +\SetExamValue{examtitle}{name=Math~1906,date=\today,version=A} \DeclareExamTemplate{examtitle}{normal}{ \begingroup \Large\noindent - \ifbool{answer}{ + \ifbool{exam@answer}{ \textcolor{red!80!black}{ \UseExamValue{examtitle}{name}\hfill\UseExamTranslation{examtitle-Solutions} } @@ -225,14 +301,14 @@ \SelectExamTemplate{examtitle}{normal} \NewDocumentCommand\examtitle{+m}{ - \SetExamTitle{#1} + \SetExamValue{examtitle}{#1} \thispagestyle{plain} - \ifbool{random}{ + \ifbool{exam@random}{ \tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{A}{ - \DeclareExamValue{examtitle}{version}{B} + \SetExamValue{examtitle}{version=B} } \tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{C}{ - \DeclareExamValue{examtitle}{version}{D} + \SetExamValue{examtitle}{version=D} } }{} \UseExamTemplate{examtitle}{default} @@ -244,17 +320,13 @@ %% total: total number of parts in current exam; %% strut: strut height in the score row. -\DeclareKeys[randexam-gradetable]{ - total .code = \DeclareExamValue{gradetable}{total}{#1} - ,total .initial:n = 6 - ,strut .code = \DeclareExamValue{gradetable}{strut}{#1} - ,strut .initial:n = 2.5em -} +\rdxm@declare@key@handler{gradetable} +\SetKeys[randexam/gradetable]{total=6,strut=2.5em} \newcounter{@exam@grade@cnt} \newrobustcmd\rdxm@part@number[1]{ \setcounter{@exam@grade@cnt}{#1} - \exam@part@number{@exam@grade@cnt} + \UseExamValue{exampart}{number}{@exam@grade@cnt} } %% #1: the tl variable; #2: the first cell; #3: the last cell @@ -288,7 +360,7 @@ {} {\UseExamValue{gradetable}{total}} \rdxm@gobble@one - \ifbool{evaluator}{ + \ifbool{exam@evaluator}{ \rdxm@table@make@row \l@rdxm@gradetable@evaluator@tl {\textbf{\UseExamTranslation{gradetable-Evaluator}} @@ -302,7 +374,7 @@ \hline \l@rdxm@gradetable@part@tl \\ \hline \l@rdxm@gradetable@score@tl \\ \hline - \ifbool{evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}{} + \ifbool{exam@evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}{} \end{tabularx} } \SelectExamTemplate{gradetable}{normal} @@ -310,7 +382,7 @@ \NewDocumentCommand\gradetable{O{}}{ \par\vspace{1em} \begingroup - \SetKeys[randexam-gradetable]{#1} + \SetKeys[randexam/gradetable]{#1} \UseExamTemplate{gradetable}{default} \endgroup } @@ -322,7 +394,7 @@ \newcommand{\rdxm@columnbox}[1]{\makebox[\columnwidth]{#1}} \newcommand{\rdxm@headleft}{\UseExamValue{examtitle}{name}} \newcommand{\rdxm@headright}{ - \ifbool{answer}{ + \ifbool{exam@answer}{ \UseExamTranslation{headfoot-Solutions} }{ \UseExamTranslation{headfoot-Name}:\hspace{12em} @@ -331,46 +403,44 @@ \newcommand{\rdxm@headtext}{\rdxm@headleft\hfill\rdxm@headright} \newcommand{\rdxm@footleft}{\UseExamValue{examtitle}{date}} \newcommand{\rdxm@footcenter}{ - \UseExamTranslation{headfoot-Page}~\thepage\space - \UseExamTranslation{headfoot-of}~\zpageref{LastPage} + \MakeExamNameNumber{\UseExamTranslation{headfoot-Page}}{\thepage} + \space + \MakeExamNameNumber{\UseExamTranslation{headfoot-of}}{\zpageref{LastPage}} } \newcommand{\rdxm@footright}{ - \UseExamTranslation{headfoot-Version}~\UseExamValue{examtitle}{version} + \MakeExamNameNumber{\UseExamTranslation{headfoot-Version}} + {\UseExamValue{examtitle}{version}} } \newcommand{\rdxm@foottext}{\rdxm@footleft\hfill\rdxm@footcenter\hfill\rdxm@footright} % fancy page style \fancyhf{} % clear head and foot -\iftwoinone - \renewcommand{\headrulewidth}{0pt}% +\ifbool{exam@twoinone}{ + \renewcommand{\headrulewidth}{0pt} \lhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}} \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}} \lfoot{\small\rdxm@columnbox{\rdxm@foottext}} \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}} -\else +}{ \lhead{\small\rdxm@headleft} \rhead{\small\rdxm@headright} \cfoot{\small\rdxm@foottext} -\fi +} % plain page style \fancypagestyle{plain}{ - \renewcommand{\headrulewidth}{0pt}% + \renewcommand{\headrulewidth}{0pt} \fancyhf{} - \iftwoinone + \ifbool{exam@twoinone}{ \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext\strut}}} \lfoot{\small\rdxm@columnbox{\rdxm@foottext}} \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}} - \else + }{ \cfoot{\small\rdxm@foottext} - \fi + } } -\ifplain - \pagestyle{plain} -\else - \pagestyle{fancy} -\fi +\ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}} %% --------------------------------------------------------------------------- %% Class option for shuffling questions: random @@ -384,17 +454,18 @@ seed .initial:n = 19061116 } -\ifrandom +\ifbool{exam@random}{ \RequirePackage{pgf} \RequirePackage{pgffor} - \newcommand*\exam@set@seed{% - %% 当\pgfmathrandom的参数为3的倍数时,对相邻种子生成的多个随机数分布不均匀 - %\pgfmathsetseed{\numexpr\rdxm@random@seed+\value{rdxm@part}-1\relax}% - %% 因此我们改用下面的方法,用随机数种子生成下一个随机数种子 - \pgfmathsetseed{\rdxm@random@seed}% - \pgfmathrandominteger\rdxm@random@seed{1}{2147483647}% + \newcommand*\exam@set@seed{ + %% When the argument of \pgfmathrandom is a multiple of three, + %% the random numbers generated by nearby seeds are not uniformly distributed + %\pgfmathsetseed{\numexpr\rdxm@random@seed+\value{exampart}-1\relax} + %% Therefore we take this approach: generating next random seed with current seed + \pgfmathsetseed{\rdxm@random@seed} + \pgfmathrandominteger\rdxm@random@seed{1}{2147483647} } -\fi +}{} %% --------------------------------------------------------------------------- %% Command for exam groups: \exampart @@ -403,20 +474,26 @@ %% Environment for solutions: solution %% --------------------------------------------------------------------------- -%% You need to put .code before .initial:n -\DeclareKeys[randexam-exampart]{% - partnumber .code = \let\exam@part@number#1, - partnumber .initial:n = \Roman, -} +\newcounter{exampart} +\renewcommand\theexampart{\Roman{exampart}} + +\rdxm@declare@key@handler{exampart} +\SetExamValue{exampart}{number=\Roman} + +%% No displaying question number when there is only one question in the part +\newbool{exam@onlyonequestion}\boolfalse{exam@onlyonequestion} -\newif\ifonlyonequestion \onlyonequestionfalse % 此部分仅有一道题时不显示题目编号 \xdef\allquestions{} \xdef\lastquestion{} -\newcounter{question} % 当前题型的小题编号 -\newcounter{questionreal} % 实际显示的小题编号,在各题型小题统一编号时使用 -\newcounter{totalquestions} % 之前各题型小题总数,在各题型小题统一编号时使用 -\newcounter{choice} % 后面选择题的 abcd 环境要用到 +%% question: problem number within current part +%% questionreal: problem number for display, used when exam@resetnumber=false +%% totalquestions: total number of problems in previous parts, used when exam@resetnumber=false +\newcounter{question} +\newcounter{questionreal} +\newcounter{totalquestions} + +\newcounter{choice} % used in abcd environment \newcommand{\hangtext}{} \newlength{\hanglength} \colorlet{part~number}{black} @@ -426,83 +503,83 @@ \newcounter{rdxm@shuffle@temp@cnt} \newcounter{rdxm@list@temp@cnt} -\newcommand\rdxm@list@print[1]{% - \par\renewcommand*{\do}[1]{(##1)}% +\newcommand\rdxm@list@print[1]{ + \par\renewcommand*{\do}[1]{(##1)} \dolistloop#1% } -\newcommand\rdxm@list@remove[2]{% +\newcommand\rdxm@list@remove[2]{ %\rdxm@list@print\rdxm@shuffle@list - \setcounter{rdxm@list@temp@cnt}{0}% - \global\let\rdxm@tmpa@list=#1% + \setcounter{rdxm@list@temp@cnt}{0} + \global\let\rdxm@tmpa@list=#1 \gdef#1{}% - \par\renewcommand*{\do}[1]{% - \stepcounter{rdxm@list@temp@cnt}% - \ifnumequal{\value{rdxm@list@temp@cnt}}{#2}{% - \def\rdxm@list@item{##1}% - %[##1]% + \par\renewcommand*{\do}[1]{ + \stepcounter{rdxm@list@temp@cnt} + \ifnumequal{\value{rdxm@list@temp@cnt}}{#2}{ + \def\rdxm@list@item{##1} + %[##1] }{ - \listxadd#1{##1}% + \listxadd#1{##1} }% }% \dolistloop\rdxm@tmpa@list } -\newcommand\rdxm@shuffle@questions{% +\newcommand\rdxm@shuffle@questions{ \exam@set@seed - \ifnumgreater{\value{question}}{2}{% - \gdef\rdxm@shuffle@list{}% - \foreach \i in {1,...,\value{question}} {\listxadd\rdxm@shuffle@list{\i}}% - %% 首尾两个小题的位置总要改变 - \pgfmathrandom{2,\value{question}}% - \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}% - \global\csletcs{rdxm@question@b@1}{rdxm@question@a@\rdxm@list@item}% + \ifnumgreater{\value{question}}{2}{ + \gdef\rdxm@shuffle@list{} + \foreach \i in {1,...,\value{question}} {\listxadd\rdxm@shuffle@list{\i}} + %% always change the postions of the first and the last questions + \pgfmathrandom{2,\value{question}} + \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult} + \global\csletcs{rdxm@question@b@1}{rdxm@question@a@\rdxm@list@item} \ifnumequal{\rdxm@list@item}{\value{question}}{ - \pgfmathrandom{\numexpr\value{question}-1\relax}% - \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}% - \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}% - }{% - \pgfmathrandom{\numexpr\value{question}-2\relax}% - \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}% - \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item}% - }% - %% 其他小题的位置没有任何限制 - \setcounter{rdxm@shuffle@temp@cnt}{1}% - \whileboolexpr{% - test{\ifnumless{\value{rdxm@shuffle@temp@cnt}}{\numexpr\value{question}-1\relax}}% - }{% - \stepcounter{rdxm@shuffle@temp@cnt}% - \pgfmathrandom{\numexpr\value{question}-\value{rdxm@shuffle@temp@cnt}\relax}% - \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult}% - \global\csletcs{rdxm@question@b@\the\value{rdxm@shuffle@temp@cnt}}{% + \pgfmathrandom{\numexpr\value{question}-1\relax} + \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult} + \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item} + }{ + \pgfmathrandom{\numexpr\value{question}-2\relax} + \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult} + \global\csletcs{rdxm@question@b@\the\value{question}}{rdxm@question@a@\rdxm@list@item} + } + %% no restrition for questions in the middle + \setcounter{rdxm@shuffle@temp@cnt}{1} + \whileboolexpr{ + test{\ifnumless{\value{rdxm@shuffle@temp@cnt}}{\numexpr\value{question}-1\relax}} + }{ + \stepcounter{rdxm@shuffle@temp@cnt} + \pgfmathrandom{\numexpr\value{question}-\value{rdxm@shuffle@temp@cnt}\relax} + \rdxm@list@remove\rdxm@shuffle@list{\pgfmathresult} + \global\csletcs{rdxm@question@b@\the\value{rdxm@shuffle@temp@cnt}}{ rdxm@question@a@\rdxm@list@item - }% - }% - }{% - \ifnumequal{\value{question}}{2}{% - \global\csletcs{rdxm@question@b@1}{rdxm@question@a@2}% - \global\csletcs{rdxm@question@b@2}{rdxm@question@a@1}% - }{}% - }% + } + } + }{ + \ifnumequal{\value{question}}{2}{ + \global\csletcs{rdxm@question@b@1}{rdxm@question@a@2} + \global\csletcs{rdxm@question@b@2}{rdxm@question@a@1} + }{} + } } -\newcommand{\printquestions}{% - \ifrandom +\newcommand{\printquestions}{ + \ifbool{exam@random}{ \rdxm@appto@questions \rdxm@shuffle@questions - \setcounter{question}{0}% + \setcounter{question}{0} \allquestions - \fi - \xdef\allquestions{}% - \xdef\lastquestion{}% + }{} + \xdef\allquestions{} + \xdef\lastquestion{} } -\newcounter{rdxm@part} - \DeclareExamTemplate{exampart}{normal}{ \noindent \textbf{ - \textcolor{part~number}{\UseExamTranslation{exampart-Part}~\Roman{rdxm@part}} + \textcolor{part~number}{ + \MakeExamNameNumber{\UseExamTranslation{exampart-Part}}{\TheExamCounter{exampart}} + } :~\UseExamValue{exampart}{type} } \space(\UseExamValue{exampart}{points}) @@ -513,21 +590,21 @@ \printquestions \setcounter{totalquestions}{\value{totalquestions}+\value{question}} \setcounter{question}{0} - \stepcounter{rdxm@part} + \stepcounter{exampart} \vspace{1em} \begingroup - \DeclareExamValue{exampart}{type}{#1} - \DeclareExamValue{exampart}{points}{#2} + \SetExamValue{exampart}{type=#1,points=#2} \UseExamTemplate{exampart}{default} \endgroup \par\nopagebreak \if\relax\detokenize{#1}\relax % #1 is empty - \onlyonequestiontrue + \booltrue{exam@onlyonequestion} \else - \onlyonequestionfalse - \vspace{1em}% + \boolfalse{exam@onlyonequestion} + \vspace{1em} \fi - %其中设定了\@nobreaktrue,保证在列表前也不分页,详情见 source2e + % \@afterheading sets \@nobreaktrue, which will prevent page breaks before lists; + % see source2e \@afterheading } @@ -542,7 +619,7 @@ \NewDocumentCommand\examdata{+m}{ \printquestions\rdxm@stop@random - \DeclareExamValue{examdata}{caption}{#1} + \SetExamValue{examdata}{caption=#1} \UseExamTemplate{examdata}{default} } @@ -550,12 +627,7 @@ \newcommand\ignorepars{\@ifnextchar\par{\expandafter\ignorepars\@gobble}{}} -% local definition, valid only in current question -\DeclareKeys[randexam-question]{ - points .store = \l@rdxm@question@points - ,level .store = \l@rdxm@question@level - ,year .store = \l@rdxm@question@year -} +\rdxm@declare@key@handler{question} \newcommand\pointorpoints[1]{ \ifnumgreater{#1}{1}{ @@ -565,26 +637,28 @@ } } -\newcommand{\questionpointstext}[1]{ (#1 \pointorpoints{#1}) } +\newcommand{\questionpointstext}[1]{ (#1~\pointorpoints{#1}) } \newcommand\rdxm@hook@exec@other@keys{} \newrobustcmd\execute@question@keys{ \rdxm@hook@exec@other@keys - \ifdefvoid{\l@rdxm@question@points}{}{\questionpointstext{\l@rdxm@question@points}} + \IfExamValueExistT{question}{points}{ + \questionpointstext{\UseExamValue{question}{points}} + } } \DeclareExamTemplate{questionbegin}{normal}{ - \ifresetnumber - \ifonlyonequestion - \renewcommand{\hangtext}{\qquad}% - \else + \ifbool{exam@resetnumber}{ + \ifbool{exam@onlyonequestion}{ + \renewcommand{\hangtext}{\qquad} + }{ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{question}}.}}\;\,} - \fi - \else - \setcounter{questionreal}{\value{totalquestions}+\value{question}}% + } + }{ + \setcounter{questionreal}{\value{totalquestions}+\value{question}} \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{questionreal}}.}}\;\,} - \fi + } \settowidth{\hanglength}{\hangtext} \description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt] \item[\hangtext]\execute@question@keys @@ -597,7 +671,7 @@ \NewDocumentEnvironment{questionreal}{O{}}{ \stepcounter{question} \setcounter{choice}{0} - \SetKeys[randexam-question]{#1} + \SetKeys[randexam/question]{#1} \UseExamTemplate{questionbegin}{default} }{ \UseExamTemplate{questionend}{default} @@ -628,30 +702,30 @@ \let \oldmedskip = \medskip \let \oldbigskip = \bigskip -\ifrandom - \newcommand\rdxm@appto@questions{% - \xappto\allquestions{\expandonce\lastquestion}% - }% - \NewEnviron{question}{% - \stepcounter{question}% +\ifbool{exam@random}{ + \newcommand\rdxm@appto@questions{ + \xappto\allquestions{\expandonce\lastquestion} + } + \NewEnviron{question}{ + \stepcounter{question} \rdxm@appto@questions - \csxdef{rdxm@question@a@\the\value{question}}{% - \unexpanded{\begin{questionreal}}% - \unexpanded\expandafter{\BODY}% - \unexpanded{\end{questionreal}}% - }% - \csxdef{rdxm@question@b@\the\value{question}}{% - \expandonce{\csname rdxm@question@a@\the\value{question}\endcsname}% - }% - \xdef\lastquestion{% - \expandonce{\csname rdxm@question@b@\the\value{question}\endcsname}% - }% + \csxdef{rdxm@question@a@\the\value{question}}{ + \unexpanded{\begin{questionreal}} + \unexpanded\expandafter{\BODY} + \unexpanded{\end{questionreal}} + } + \csxdef{rdxm@question@b@\the\value{question}}{ + \expandonce{\csname rdxm@question@a@\the\value{question}\endcsname} + } + \xdef\lastquestion{ + \expandonce{\csname rdxm@question@b@\the\value{question}\endcsname} + } } - \NewEnviron{solution}{% - \csxappto{rdxm@question@a@\the\value{question}}{% - \unexpanded{\begin{solutionreal}}% - \expandonce{\BODY}% - \unexpanded{\end{solutionreal}}% + \NewEnviron{solution}{ + \csxappto{rdxm@question@a@\the\value{question}}{ + \unexpanded{\begin{solutionreal}} + \expandonce{\BODY} + \unexpanded{\end{solutionreal}} }% } \renewcommand{\newpage}{\gappto\lastquestion{\oldnewpage}} @@ -659,54 +733,47 @@ \renewcommand{\smallskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldsmallskip}} \renewcommand{\medskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldmedskip}} \renewcommand{\bigskip}{\csgappto{rdxm@question@a@\the\value{question}}{\oldbigskip}} -\else +}{ \newenvironment{question}[1][]{\questionreal[#1]}{\endquestionreal} %\newenvironment{solution}{\solutionreal}{\endsolutionreal} \NewEnviron{solution}{\begin{solutionreal}\BODY\end{solutionreal}} -\fi +} -\newcommand{\rdxm@stop@random}{% - \ifrandom - \renewenvironment{question}{\questionreal}{\endquestionreal}% - \renewenvironment{solution}{\solutionreal}{\endsolutionreal}% +\newcommand{\rdxm@stop@random}{ + \ifbool{exam@random}{ + \renewenvironment{question}{\questionreal}{\endquestionreal} + \renewenvironment{solution}{\solutionreal}{\endsolutionreal} \let \newpage = \oldnewpage \let \vfill = \oldvfill \let \smallskip = \oldsmallskip \let \medskip = \oldmedskip \let \bigskip = \oldbigskip - \fi + }{} } \def\CommentCutFile{\jobname.cut} -\AtBeginDocument{% - \ifanswer\else - \excludecomment{solution} - \fi +\AtBeginDocument{ + \ifbool{exam@answer}{}{\excludecomment{solution}} } %% --------------------------------------------------------------------------- %% Command for answer tables: \answertable %% --------------------------------------------------------------------------- -%% property .store is the same as .tl_set:N in ltkeys. -%% you need to put .code before .initial:n. %% total: total number of questions in current exam part; %% column: number of questions in each answer row; %% strut: strut height in each answer rows; %% notice: notice text before the answer table. -\DeclareKeys[randexam-answertable]{ - total .code = \DeclareExamValue{answertable}{total}{#1} - ,column .code = \DeclareExamValue{answertable}{column}{#1} - ,strut .code = \DeclareExamValue{answertable}{strut}{#1} - ,strut .initial:n = 1em - ,notice .code = \DeclareExamValue{answertable}{notice}{#1} - ,notice .initial:n = {Notice:~you~MUST~write~the~answers~in~the~following~tables.} +\rdxm@declare@key@handler{answertable} +\SetKeys[randexam/answertable]{ + strut = 1em + ,notice = {Notice:~you~MUST~write~the~answers~in~the~following~tables.} } -\gdef\answer@lines@temp{}% -\newcommand{\answer@lines@add}[1]{% - \xdef\answer@lines@temp{\answer@lines@temp#1}% +\gdef\answer@lines@temp{} +\newcommand{\answer@lines@add}[1]{ + \xdef\answer@lines@temp{\answer@lines@temp#1} } \newrobustcmd\answer@number@hided[1]{\UseExamTranslation{answertable-Number}} @@ -719,38 +786,39 @@ \newcounter{answer@total} %% #1: strut; #2: total; #3: column. -\newcommand{\answer@lines}[3]{% - \setcounter{answer@row}{(#2-1)/#3+1}% 除法向下取整,改为向上取整 +\newcommand{\answer@lines}[3]{ + % change rounding down to rounding up in the division + \setcounter{answer@row}{(#2-1)/#3+1} \begingroup - \let\hline=\relax \let\\=\relax % 禁止展开 - \gdef\answer@lines@temp{}% - \setcounter{answer@total}{1}% + \let\hline=\relax \let\\=\relax % forbid expansions + \gdef\answer@lines@temp{} + \setcounter{answer@total}{1} \whileboolexpr{ test{\ifnumgreater{\value{answer@row}}{0}} - }{% - \addtocounter{answer@row}{-1}% - \answer@lines@add{\answer@number@hided}% - \setcounter{answer@col}{1}% - \unlessboolexpr{% - test{\ifnumgreater{\value{answer@col}}{#3}}% - }{% - \answer@lines@add{&}% - \ifnumgreater{\value{answer@total}}{#2}{}{% - \answer@lines@add{\arabic{answer@total}}% - }% - \stepcounter{answer@col}% - \stepcounter{answer@total}% - }% - \answer@lines@add{\\ \hline \answer@cell@strut{#1}}% - \setcounter{answer@col}{1}% + }{ + \addtocounter{answer@row}{-1} + \answer@lines@add{\answer@number@hided} + \setcounter{answer@col}{1} \unlessboolexpr{ test{\ifnumgreater{\value{answer@col}}{#3}} - }{% - \answer@lines@add{&}% - \stepcounter{answer@col}% - }% - \answer@lines@add{\\ \hline}% - }% + }{ + \answer@lines@add{&} + \ifnumgreater{\value{answer@total}}{#2}{}{ + \answer@lines@add{\arabic{answer@total}} + } + \stepcounter{answer@col} + \stepcounter{answer@total} + } + \answer@lines@add{\\ \hline \answer@cell@strut{#1}} + \setcounter{answer@col}{1} + \unlessboolexpr{ + test{\ifnumgreater{\value{answer@col}}{#3}} + }{ + \answer@lines@add{&} + \stepcounter{answer@col} + } + \answer@lines@add{\\ \hline} + } \endgroup \answer@lines@temp } @@ -767,7 +835,7 @@ \NewDocumentCommand\answertable{O{}}{ \begingroup - \SetKeys[randexam-answertable]{#1} + \SetKeys[randexam/answertable]{#1} \UseExamTemplate{answertable}{default} \endgroup \par\vspace{0.8em} @@ -780,7 +848,7 @@ %% Command for multiple-choice questions: \pickin and \pickout %% --------------------------------------------------------------------------- -\newcommand{\answer}[1]{\ifanswer#1\else\phantom{#1}\fi} +\newcommand{\answer}[1]{\ifbool{exam@answer}{#1}{\phantom{#1}}} \newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax} @@ -798,18 +866,19 @@ \newcommand*{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}} \newcommand*{\fillin}[1]{\underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}} -\newcommand*\pickoutreal[1]{% - \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})% +\newcommand*\pickoutreal[1]{ + \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}}) } -\newcommand*\pickinreal[1]{% +\newcommand*\pickinreal[1]{ \unskip\nobreak - \hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}% + \hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em} \ignorespaces } -%% 选择题四个选项打乱顺序,用三种方法即可保证答案不同 +%% We choose three ways for shuffling four choices in a multiple-choice question %% 1:ABCD -> CDAB; 2:ABCD -> BADC; 3: ABCD -> DCBA -%% 即在两行排列时仅用到上下交换以及左右交换,这样可以保持两行长度不变 +%% In other word, we only exchange choices in the same row or column, +%% so as to make the lengths of choice lines unchanged \csdef{rdxm@shuffle@1@A}{C} \csdef{rdxm@shuffle@2@A}{B} \csdef{rdxm@shuffle@3@A}{D} \csdef{rdxm@shuffle@1@B}{D} \csdef{rdxm@shuffle@2@B}{A} \csdef{rdxm@shuffle@3@B}{C} @@ -819,33 +888,33 @@ \def\@rdxm@choice@random{0} \newcommand\rdxm@shuffle@abcd[1]{\csuse{rdxm@shuffle@\@rdxm@choice@random @#1}} -\newcommand*\pickout[1]{% - \ifbool{random}{% +\newcommand*\pickout[1]{ + \ifbool{exam@random}{ \exam@set@seed - \pgfmathrandominteger\@rdxm@choice@random{1}{3}% + \pgfmathrandominteger\@rdxm@choice@random{1}{3} %\@rdxm@choice@random - \pickoutreal{\rdxm@shuffle@abcd{#1}}% - }{% - \pickoutreal{#1}% - }% + \pickoutreal{\rdxm@shuffle@abcd{#1}} + }{ + \pickoutreal{#1} + } } -\newcommand*\pickoutfixed[1]{% - \pickoutreal{#1}% - \randomfalse +\newcommand*\pickoutfixed[1]{ + \pickoutreal{#1} + \boolfalse{exam@random} } -\newcommand*\pickin[1]{% - \ifbool{random}{% +\newcommand*\pickin[1]{ + \ifbool{exam@random}{ \exam@set@seed - \pgfmathrandominteger\@rdxm@choice@random{1}{3}% + \pgfmathrandominteger\@rdxm@choice@random{1}{3} %\@rdxm@choice@random - \pickinreal{\rdxm@shuffle@abcd{#1}}% - }{% - \pickinreal{#1}% - }% + \pickinreal{\rdxm@shuffle@abcd{#1}} + }{ + \pickinreal{#1} + } } -\newcommand*\pickinfixed[1]{% - \pickinreal{#1}% - \randomfalse +\newcommand*\pickinfixed[1]{ + \pickinreal{#1} + \boolfalse{exam@random} } %% --------------------------------------------------------------------------- @@ -856,17 +925,17 @@ \newlength{\rdxm@item@len} \newlength{\rdxm@label@len} -\newcommand\rdxm@item@temp{% - \unskip\cr\stepcounter{choice}(\Alph{choice})\ % +\newcommand\rdxm@item@temp{ + \unskip\cr\stepcounter{choice}(\Alph{choice})\ } -\newcommand\rdxm@item@box{% +\newcommand\rdxm@item@box{ \hfill\egroup\hfill\hbox to \rdxm@item@len\bgroup \stepcounter{choice}(\Alph{choice})\ \ignorespaces } -\newcommand\rdxm@item@par{% - \stepcounter{choice}% - \def\rdxm@label@text{(\Alph{choice})\ }% - \settowidth{\rdxm@label@len}{\rdxm@label@text}% +\newcommand\rdxm@item@par{ + \stepcounter{choice} + \def\rdxm@label@text{(\Alph{choice})\ } + \settowidth{\rdxm@label@len}{\rdxm@label@text} \par \parshape 2 \hanglength \linewidth \dimexpr\hanglength + \rdxm@label@len\relax \dimexpr\linewidth - \rdxm@label@len\relax @@ -875,87 +944,87 @@ \NewEnviron{abcdreal}{ \unskip - \setlength{\parindent}{0pt}% - \setlength{\parskip}{0pt}% - \setcounter{choice}{0}% + \setlength{\parindent}{0pt} + \setlength{\parskip}{0pt} + \setcounter{choice}{0} \let\item=\rdxm@item@temp - \settowidth{\rdxm@item@len}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}% - \setcounter{choice}{0}% + \settowidth{\rdxm@item@len}{\vbox{\halign{##\hfil\cr\BODY\crcr}}} + \setcounter{choice}{0} \ifdim\rdxm@item@len>0.486\linewidth - \setlength{\rdxm@item@len}{\linewidth}% + \setlength{\rdxm@item@len}{\linewidth} \let\item=\rdxm@item@par \BODY\par \else \ifdim\rdxm@item@len>.243\linewidth - \setlength{\rdxm@item@len}{0.5\linewidth}% + \setlength{\rdxm@item@len}{0.5\linewidth} \else - \setlength{\rdxm@item@len}{0.25\linewidth}% + \setlength{\rdxm@item@len}{0.25\linewidth} \fi \let\item=\rdxm@item@box \par\bgroup\BODY\hfill\egroup\par \fi } -\newcommand\rdxm@item@one@line{% +\newcommand\rdxm@item@one@line{ \unskip \ifnumequal{\value{choice}}{0}{}{\hfill} - \stepcounter{choice}(\Alph{choice})\ % + \stepcounter{choice}(\Alph{choice})\ } -\newcommand\rdxm@item@two@line{% +\newcommand\rdxm@item@two@line{ \unskip - \ifnumodd{\value{choice}}{&}{\unskip\cr}% - \stepcounter{choice}(\Alph{choice})\ % + \ifnumodd{\value{choice}}{&}{\unskip\cr} + \stepcounter{choice}(\Alph{choice})\ } \NewEnviron{abcd*real}{ \unskip - \setlength{\parindent}{0pt}% - \setlength{\parskip}{0pt}% - \setcounter{choice}{0}% + \setlength{\parindent}{0pt} + \setlength{\parskip}{0pt} + \setcounter{choice}{0} \let\item=\rdxm@item@one@line - \settowidth{\rdxm@item@len}{\BODY}% + \settowidth{\rdxm@item@len}{\BODY} \ifdim\rdxm@item@len<0.95\linewidth - \setcounter{choice}{0}% + \setcounter{choice}{0} \par\bgroup\BODY\hfill\hfill\par\egroup\par \else - \setcounter{choice}{0}% + \setcounter{choice}{0} \let\item=\rdxm@item@two@line - \settowidth{\rdxm@item@len}{\vbox{\halign{##&##\hfil\cr\BODY\crcr}}}% + \settowidth{\rdxm@item@len}{\vbox{\halign{##&##\hfil\cr\BODY\crcr}}} \ifdim\rdxm@item@len<0.975\linewidth - \setcounter{choice}{0}% + \setcounter{choice}{0} \par\bgroup\nointerlineskip - \vbox{\halign to\linewidth{##\hfil\tabskip=0pt plus 1fil&##\hfil\cr\BODY\crcr}}% + \vbox{\halign to\linewidth{##\hfil\tabskip=0pt plus 1fil&##\hfil\cr\BODY\crcr}} \egroup\par \else - \setcounter{choice}{0}% + \setcounter{choice}{0} \let\item=\rdxm@item@par \par\bgroup\BODY\hfill\egroup\par \fi \fi } -\ifbool{random}{% +\ifbool{exam@random}{ \csdef{rdxm@swap@items@1}#1#2#3#4{\item#3\item#4\item#1\item#2} \csdef{rdxm@swap@items@2}#1#2#3#4{\item#2\item#1\item#4\item#3} \csdef{rdxm@swap@items@3}#1#2#3#4{\item#4\item#3\item#2\item#1} - \long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{% - #1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5}% + \long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{ + #1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5} } }{} -\NewDocumentEnvironment{abcd}{+b}{% - \ifbool{random}{% - \begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal}% - }{% - \begin{abcdreal}#1\end{abcdreal}% - }% +\NewDocumentEnvironment{abcd}{+b}{ + \ifbool{exam@random}{ + \begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal} + }{ + \begin{abcdreal}#1\end{abcdreal} + } }{} -\NewDocumentEnvironment{abcd*}{+b}{% - \ifbool{random}{% - \begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real}% - }{% - \begin{abcd*real}#1\end{abcd*real}% - }% +\NewDocumentEnvironment{abcd*}{+b}{ + \ifbool{exam@random}{ + \begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real} + }{ + \begin{abcd*real}#1\end{abcd*real} + } }{} %% --------------------------------------------------------------------------- @@ -971,8 +1040,8 @@ %% Use freealign package to align math formulas in different lines %% --------------------------------------------------------------------------- -\AtBeginDocument{% - \ifbool{freealign}{\RequirePackage{freealign}}{}% +\AtBeginDocument{ + \ifbool{exam@freealign}{\RequirePackage{freealign}}{} } %% --------------------------------------------------------------------------- @@ -982,31 +1051,31 @@ \PassOptionsToPackage{tbtags}{amsmath} \RequirePackage{amsmath} -\newcommand{\solutionpointstext}[1]{% - \textcolor{red}{#1\kern0.15em\pointorpoints{#1}}% +\newcommand{\solutionpointstext}[1]{ + \textcolor{red}{#1\kern0.15em\pointorpoints{#1}} } -\newcommand{\pointstext}[1]{% - \mbox{}\nobreak\hfill$\cdots\cdots$\solutionpointstext{#1}% +\newcommand{\pointstext}[1]{ + \mbox{}\nobreak\hfill$\cdots\cdots$\solutionpointstext{#1} \par\noindent\ignorespaces } \newcommand{\pointseqno}[1]{\eqno{\cdots\cdots\text{\solutionpointstext{#1}}}} \newcommand{\pointstag}[1]{\tag*{$\cdots\cdots$\solutionpointstext{#1}}} -\newrobustcmd{\points}[1]{% - \ifbool{mmode}{% - \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}}% - }{% - \pointstext{#1}% - }% +\newrobustcmd{\points}[1]{ + \ifbool{mmode}{ + \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}} + }{ + \pointstext{#1} + } } %% --------------------------------------------------------------------------- %% Use medium-size fractions and operators in both inline and displayed formulas %% --------------------------------------------------------------------------- -\AtBeginDocument{% - \ifbool{medmath}{\RequirePackage{medmath}}{}% +\AtBeginDocument{ + \ifbool{exam@medmath}{\RequirePackage{medmath}}{} } %% --------------------------------------------------------------------------- @@ -1022,150 +1091,268 @@ \setlength\arraycolsep{4pt} -\RequirePackage{diagbox} -%% 修正 \diagbox 在 array 环境中使用的问题 -\newrobustcmd{\diagboxtwo}[3][]{% - \ifbool{mmode}{% - \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}}% - }{% - \diagbox[#1]{#2}{#3}% +\newrobustcmd\rdxm@moremath@diagbox{ + \RequirePackage{diagbox} + %% Fix problem in using \diagbox in array environment + \newrobustcmd{\diagboxtwo}[3][]{ + \ifbool{mmode}{ + \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}} + }{ + \diagbox[##1]{##2}{##3} + } + } + \newrobustcmd{\diagboxthree}[4][]{ + \ifbool{mmode}{ + \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}{$##4$}} + }{ + \diagbox[##1]{##2}{##3}{##4} + } } } -\newrobustcmd{\diagboxthree}[4][]{% - \ifbool{mmode}{% - \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}{$#4$}}% - }{% - \diagbox[#1]{#2}{#3}{#4}% + +\newrobustcmd\rdxm@moremath@limits{ + \AtBeginDocument{ + \let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits} + \let\rdxm@saved@sum=\sum \def\sum{\rdxm@saved@sum\limits} + \let\rdxm@saved@prod=\prod \def\prod{\rdxm@saved@prod\limits} } } -\RequirePackage{mathtools} % \mathllap 命令,pmatrix* 环境等 -\RequirePackage{extarrows} - -\AtBeginDocument{% - \let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits}% - \let\rdxm@saved@sum=\sum \def\sum{\rdxm@saved@sum\limits}% - \let\rdxm@saved@prod=\prod \def\prod{\rdxm@saved@prod\limits}% -} - -\newcommand{\e}{\mathrm{e}} -\newcommand{\R}{\mathbb{R}} - -\DeclareMathOperator{\arccot}{arccot} -\DeclareMathOperator{\Corr}{\rho} -\DeclareMathOperator{\Cov}{Cov} -\DeclareMathOperator{\diag}{diag} -\DeclareMathOperator{\grad}{grad} -\DeclareMathOperator{\Prj}{Prj} -\DeclareMathOperator{\tr}{tr} -\DeclareMathOperator{\Var}{Var} - -\DeclareMathOperator{\diver}{div} -\let\division=\div -\let\div=\diver - -\newcommand{\diff}{\mathop{}\!\mathrm{d}} -\newcommand{\dx}{\diff x} -\newcommand{\dy}{\diff y} -\def\dz{\diff z} % 不确定命令是否已经定义 -\newcommand{\du}{\diff u} -\newcommand{\dv}{\diff v} -\newcommand{\dr}{\diff r} -\newcommand{\ds}{\diff s} -\newcommand{\dt}{\diff t} -\newcommand{\dS}{\diff S} -% 有些宏包比如 hyperref 会修改 \d 的定义,所以放在 document 开始处 -% 利用 etoolbox 将 \d 定义为健壮命令,以避免在 align 等环境中错误地展开 -\AtBeginDocument{% - \let\oldd=\d - \renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}}% -} - -\let\pd=\partial -\newcommand{\pdf}{\pd f} -\newcommand{\pdg}{\pd g} -\newcommand{\pdh}{\pd h} -\newcommand{\pdl}{\pd l} -\newcommand{\pdn}{\pd n} -\newcommand{\pdu}{\pd u} -\newcommand{\pdv}{\pd v} -\newcommand{\pdx}{\pd x} -\newcommand{\pdy}{\pd y} -\newcommand{\pdz}{\pd z} -\newcommand{\pdF}{\pd F} -\newcommand{\pdL}{\pd L} -\newcommand{\pdP}{\pd P} -\newcommand{\pdQ}{\pd Q} -\newcommand{\pdR}{\pd R} - -% from mathabx package -\DeclareFontFamily{U}{mathx}{\hyphenchar\font45} -\DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{} -\DeclareSymbolFont{mathx}{U}{mathx}{m}{n} -\DeclareMathAccent{\widebar}{0}{mathx}{"73} - -\newcommand{\va}{\vec{a}} -\newcommand{\vb}{\vec{b}} -\newcommand{\vc}{\vec{c}} -\newcommand{\vd}{\vec{d}} -\newcommand{\ve}{\vec{e}} -\newcommand{\vi}{\vec{i}} -\newcommand{\vj}{\vec{j}} -\newcommand{\vk}{\vec{k}} -\newcommand{\vn}{\vec{n}} -\newcommand{\vs}{\vec{s}} -\newcommand{\vv}{\vec{v}} - -\let\ov=\overrightarrow - -\let\le=\leqslant -\let\ge=\geqslant - -\let\lb=\{ -\let\rb=\} - -\def\T{\mathrm{T}\kern-.5pt} - -% 分数线长一点的分数,\wfrac[2pt]{x}{y} 表示左右加 2pt -% 和前面的 medmath 一样,将代码放在 \AtBeginDocument 里 -\AtBeginDocument{% - \newrobustcmd{\wfrac}[3][2pt]{% - \frac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}% - }% - \newrobustcmd{\wdfrac}[3][2pt]{% - \dfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}% - }% - \newrobustcmd{\wtfrac}[3][2pt]{% - \tfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}% - }% +\newrobustcmd\rdxm@moremath@differential{ + \newcommand{\diff}{\mathop{}\!\mathrm{d}} + \newcommand{\dx}{\diff x} + \newcommand{\dy}{\diff y} + \def\dz{\diff z} % not sure whether it has been defined + \newcommand{\du}{\diff u} + \newcommand{\dv}{\diff v} + \newcommand{\dr}{\diff r} + \newcommand{\ds}{\diff s} + \newcommand{\dt}{\diff t} + \newcommand{\dS}{\diff S} + %% Some packages such as hyperref will modify the definition of \d, + %% so we put the code in \AtBeginDocument. + %% Also we define \d as a protected command, so as to avoid wrong expansions of + %% it at the beginning of math arrays such as align from amsmath package. + \AtBeginDocument{ + \let\oldd=\d + \renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}} + } + \let\pd=\partial + \newcommand{\pdf}{\pd f} + \newcommand{\pdg}{\pd g} + \newcommand{\pdh}{\pd h} + \newcommand{\pdl}{\pd l} + \newcommand{\pdn}{\pd n} + \newcommand{\pdu}{\pd u} + \newcommand{\pdv}{\pd v} + \newcommand{\pdx}{\pd x} + \newcommand{\pdy}{\pd y} + \newcommand{\pdz}{\pd z} + \newcommand{\pdF}{\pd F} + \newcommand{\pdL}{\pd L} + \newcommand{\pdP}{\pd P} + \newcommand{\pdQ}{\pd Q} + \newcommand{\pdR}{\pd R} +} + +\newrobustcmd\rdxm@moremath@widebar{ + %% from mathabx package + \DeclareFontFamily{U}{mathx}{\hyphenchar\font45} + \DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{} + \DeclareSymbolFont{mathx}{U}{mathx}{m}{n} + \DeclareMathAccent{\widebar}{0}{mathx}{"73} +} + +\newrobustcmd\rdxm@moremath@vector{ + \newcommand{\va}{\vec{a}} + \newcommand{\vb}{\vec{b}} + \newcommand{\vc}{\vec{c}} + \newcommand{\vd}{\vec{d}} + \newcommand{\ve}{\vec{e}} + \newcommand{\vi}{\vec{i}} + \newcommand{\vj}{\vec{j}} + \newcommand{\vk}{\vec{k}} + \newcommand{\vn}{\vec{n}} + \newcommand{\vs}{\vec{s}} + \newcommand{\vv}{\vec{v}} +} + +\newrobustcmd\rdxm@moremath@widefrac{ + %% Longer fraction rules, \wfrac[2pt]{x}{y} will add 2pt to the left and right + \AtBeginDocument{ + \newrobustcmd{\wfrac}[3][2pt]{ + \frac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}} + } + \newrobustcmd{\wdfrac}[3][2pt]{ + \dfrac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}} + } + \newrobustcmd{\wtfrac}[3][2pt]{ + \tfrac{\hspace{##1}##2\hspace{##1}}{\hspace{##1}##3\hspace{##1}} + } + } } -% 使用 stix font 中的 white arrows -\AtBeginDocument{\@ifpackageloaded{fontspec}{% +\newrobustcmd\rdxm@moremath@whitearrow{ + %% 使用 stix font 中的 white arrows + \AtBeginDocument{\@ifpackageloaded{fontspec}{ %\IfFileExists{STIX-Regular.otf}{% 在 TeXLive 中无效 - \IfFileExists{stix.sty}{% - \newfontfamily{\@rdxm@stix}{STIX} % stix v1.1 - }{% - \newfontfamily{\@rdxm@stix}{STIXGeneral} % stix v1.0 + \IfFileExists{stix.sty}{ + \newfontfamily{\@rdxm@stix}{STIX} % stix v1.1 + }{ + \newfontfamily{\@rdxm@stix}{STIXGeneral} % stix v1.0 } - \newrobustcmd\leftwhitearrow{% - \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E6}}}% + \newrobustcmd\leftwhitearrow{ + \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E6}}} } - \newrobustcmd\upwhitearrow{% - \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E7}}}% + \newrobustcmd\upwhitearrow{ + \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E7}}} } - \newrobustcmd\rightwhitearrow{% - \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E8}}}% + \newrobustcmd\rightwhitearrow{ + \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E8}}} } - \newrobustcmd\downwhitearrow{% - \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E9}}}% + \newrobustcmd\downwhitearrow{ + \mathrel{\text{\normalfont\@rdxm@stix\symbol{"21E9}}} } -}{% + }{ \let \leftwhitearrow = \Leftarrow \let \rightwhitearrow = \Rightarrow \let \upwhitearrow = \Uparrow \let \downwhitearrow = \Downarrow -}} + }} +} + +\newrobustcmd\rdxm@moremath@miscellaneous{ + \RequirePackage{mathtools} % for \mathllap command,pmatrix* environment + \RequirePackage{extarrows} + \newcommand{\e}{\mathrm{e}} + \newcommand{\R}{\mathbb{R}} + \DeclareMathOperator{\arccot}{arccot} + \DeclareMathOperator{\Corr}{\rho} + \DeclareMathOperator{\Cov}{Cov} + \DeclareMathOperator{\diag}{diag} + \DeclareMathOperator{\grad}{grad} + \DeclareMathOperator{\Prj}{Prj} + \DeclareMathOperator{\tr}{tr} + \DeclareMathOperator{\Var}{Var} + \DeclareMathOperator{\diver}{div} + \let\division=\div + \let\div=\diver + \let\ov=\overrightarrow + \let\le=\leqslant + \let\ge=\geqslant + \let\lb=\{ + \let\rb=\} + \def\T{\mathrm{T}\kern-.5pt} +} + +\ifbool{exam@moremath}{ + \rdxm@moremath@diagbox + \rdxm@moremath@limits + \rdxm@moremath@differential + \rdxm@moremath@widebar + \rdxm@moremath@vector + \rdxm@moremath@widefrac + \rdxm@moremath@whitearrow + \rdxm@moremath@miscellaneous +}{} + +%% --------------------------------------------------------------------------- +%% Load local user config file +%% --------------------------------------------------------------------------- + +\InputIfFileExists{randexam.cfg}{}{} + +%% --------------------------------------------------------------------------- +%% Support for Chinese Language +%% --------------------------------------------------------------------------- + +\newrobustcmd\rdxm@chinese@ctex{ + %% 四号 小四号 五号 小五号 + %% 14bp 12bp 10.5bp 9bp + %% 实际上,在旧版本 ctex 中只能用 cs4size 和 c5size 选项 + %% 而新版本 ctex 中,可以利用 zihao 选项指定各种中文字号 + \PassOptionsToPackage{CJKnumber}{xeCJK} + \RequirePackage[cs4size,UTF8,noindent,heading]{ctex} + \ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}} + %% 在旧版本 xeCJK 中,必须用 CJKnumber 选项载入 CJKnumb 包,后面才载入会报错 + %% 但在新版本 xeCJK 中 CJKnumber 选项已经被废弃,需要在后面自行载入它 + %% 在 xeCJK 中已经禁止载入 CJK,但是在新版本 ctex 宏包中却失效了 + %% 我们假装 CJK 已经载入,再载入 CJKnumb,避免出现 \CJKglue 重复定义的问题 + %% 注意用 PDFLaTeX 编译时需要用到 CJK,所以只在未定义时才作修改 + \ifdefined\CJKglue + \@namedef{ver@CJK.sty}{} + %\@namedef{opt@CJK.sty}{} + \fi + \RequirePackage{CJKnumb} + %% 新版本 xeCJK 已经废弃并禁用 CJKfntef,改用 xeCJKfntef 取代,我们需要载入后者 + %% 注意要保证能在较旧的 TeX 系统中编译,我们只能用 \ifXeTeX 而不能用 \ifxetex + %% 因为旧版本 iftex 宏包只有 \ifXeTeX 命令,而 ifxetex 宏包才有 \ifxetex 命令 + %% 在 2019 年 10 月,LaTeX 开发团队接管了 iftex 宏包,新版本同时提供这两个命令 + \RequirePackage{CJKfntef} + \RequirePackage{iftex} + \ifXeTeX\@ifpackagelater{xeCJK}{2020/02/10}{\RequirePackage{xeCJKfntef}}{}\fi + \ifbool{XeTeX}{ + % https://en.wikipedia.org/wiki/Number_Forms + % Ⅰ、Ⅱ、Ⅲ、Ⅳ、Ⅴ、Ⅵ、Ⅶ、Ⅷ、Ⅸ、Ⅹ、Ⅺ、Ⅻ + \xeCJKsetcharclass{"2150}{"218F}{1} % 斜线分数,全角罗马数字等 + % https://en.wikipedia.org/wiki/Enclosed_Alphanumerics + \xeCJKsetcharclass{"2460}{"24FF}{1} % 带圈数字字母,括号数字字母,带点数字等 + }{} +} +\ifbool{exam@ctex}{\rdxm@chinese@ctex}{} + +\newrobustcmd\rdxm@chinese@sourcehan{ + \setCJKmainfont[BoldFont=Source~Han~Sans~SC]{Source~Han~Serif~SC} + \setCJKsansfont{Source~Han~Sans~SC} + %% 用中文字体名时 LuaTeX 找不到该字体,XeTeX 正常 + %\setCJKmainfont[BoldFont=思源黑体]{思源宋体} + %\setCJKsansfont{思源黑体} +} +\AtBeginDocument{ + \ifbool{exam@sourcehan}{ + \ifbool{XeTeX}{\rdxm@chinese@sourcehan}{ + \ifbool{LuaTeX}{\rdxm@chinese@sourcehan}{} + } + }{} +} + +%% 这里不能用 \ifbool,因为涉及到 catcode 的改变 +\ifexam@solidot + \ifXeTeX + \catcode`。=\active\def。{.} + \else\ifLuaTeX + \catcode`。=\active\def。{.} + \fi + \fi +\fi + +%% Chinese translations of keywords +\DeclareExamTranslation{chinese}{ + answertable-Answer = 答案 + ,answertable-Number = 小题 + ,examdata-Appendix = 附录 + ,exampart-Part = {第,部分} + ,examtitle-Name = 姓名 + ,examtitle-Solutions = 试卷解答 + ,gradetable-Evaluator = 评阅人 + ,gradetable-Part = 部分 + ,gradetable-Score = 得分 + ,gradetable-Total = 总分 + ,headfoot-Name = 姓名 + ,headfoot-of = {共,页} + ,headfoot-Page = {第,页} + ,headfoot-Solutions = 试卷解答 + ,headfoot-Version = {\relax,卷} + ,points-point = 分 + ,points-points = 分 + ,question-Question = 题 + ,solution-Solution = 解 +} +\ifbool{exam@ctex}{\SelectExamTranslation{chinese}}{} + +%% --------------------------------------------------------------------------- +%% Stop ignoring spaces in the code +%% --------------------------------------------------------------------------- \IgnoreSpacesOff diff --git a/macros/latex/contrib/randexam/randexam.pdf b/macros/latex/contrib/randexam/randexam.pdf index 2faabec1c8..307234cc1c 100644 Binary files a/macros/latex/contrib/randexam/randexam.pdf and b/macros/latex/contrib/randexam/randexam.pdf differ diff --git a/macros/latex/contrib/randexam/randexam.tex b/macros/latex/contrib/randexam/randexam.tex index feb1af2e14..382375dc11 100644 --- a/macros/latex/contrib/randexam/randexam.tex +++ b/macros/latex/contrib/randexam/randexam.tex @@ -1,9 +1,9 @@ % -*- coding: utf-8 -*- -\documentclass[12pt,plain,most]{randexam} +\documentclass[12pt,plain,math=most]{randexam} \geometry{b5paper,margin=2cm} -\newcommand*{\myversion}{2024C} +\newcommand*{\myversion}{2024D} \newcommand*{\mydate}{\the\year-\mylpad\month-\mylpad\day} \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi} @@ -28,6 +28,7 @@ \renewcommand{\arraystretch}{1.3} \usepackage{tabularx} +\usepackage{booktabs} \newcommand{\fillbox}[1]{\ulinefill{#1}\underline{#1}\ulinefill{#1}} @@ -361,7 +362,7 @@ The meanings of keys in the \verb!\gradetable! command are: \subsection{Answer tables} Before true-or-false, fill-in-the-blank, or multiple-choice questions, -you may use \mycmd{\answertable} to generate an blank answer table: +you may use \mycmd{\answertable} to generate a blank answer table: \begin{code} \answertable[total=6,column=3,strut=3em] @@ -427,9 +428,19 @@ you could modify the translation of \mykey{solution-Solution} keyword The following example changes it from "Solution" to "Proof": \begin{code} -\DeclareExamTranslation{current}{solution-Solution=Proof} +\SetExamTranslation{solution-Solution=Proof} +\begin{solution} + This is the proof. +\end{solution} \end{code} +\begingroup +\SetExamTranslation{solution-Solution=Proof} +\begin{solution} + This is the proof. +\end{solution} +\endgroup + \subsection{Points command} Inside \myenv{solution} environment, you could use \mycmd{\points} to give points for each step. @@ -452,7 +463,7 @@ And the point text will be printed at the right edge of the line. \subsection{Alignment commands} -With class option \myopt{many}, \mypkg{randexam} will load \mypkg{freealign} package. +With class option \myopt{freealign}, \mypkg{randexam} loads \mypkg{freealign} package, and \mypkg{freealign} package provides several commands for aligning math formulas in different lines. Here is the first example: @@ -491,10 +502,37 @@ you need two compilations to get correct results. \section{Class options} +All options provided by \mypkg{randexam} class are listed in the following table: + +\begin{tabularx}{\linewidth}{@{}lX@{}} +\toprule + \myopt{noanswer} & hide all answers in the exam paper \\ + \myopt{random} & shuffle questions in each part \\ + \myopt{seed} & the random seed used by \myopt{random} option \\ +\midrule + \myopt{plain} & set page style \myval{plain} \\ + \myopt{a3paper} & typeset a two-column paper of A3 size \\ + \myopt{a3input} & input a paper of A4 size and change it to A3 size \\ +\midrule + \myopt{mathdesign} & use \mypkg{mathdesign} utopia font \\ + \myopt{freealign} & load \mypkg{freealign} package \\ + \myopt{medmath} & load \mypkg{medmath} package \\ + \myopt{moremath} & define more math commands \\ + \myopt{math=many} & $\Leftrightarrow$ \myopt{mathdesign,freealign} \\ + \myopt{math=most} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath} \\ + \myopt{math=all} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath,moremath} \\ +\midrule + \myopt{chinese} & select Chinese language and load \mypkg{ctex} package \\ +\bottomrule +\end{tabularx} + +Some of the options could also be modified with \mycmd{\SetExamOption}: +\myopt{noanswer}, \myopt{random}, and \myopt{seed}. + \subsection{Blank exam papers} Assume \myfile{exam-a-answer.tex} is an exam paper with answers. -You can easily get an blank exam paper with answers removed, +You can easily get a blank exam paper with answers removed, by creating an \myfile{exam-a-blank.tex} file with the following lines: \begin{code} @@ -508,7 +546,7 @@ The answers will be hidden in the compiled exam paper. \subsection{Randomized variants}\label{opt:random} Assume \myfile{exam-a-answer.tex} is an exam paper. -You can get an randomized variant with all questions in the same part shuffled, +You could get a randomized variant with all questions in the same part shuffled, by creating an \myfile{exam-b-answer.tex} file with the following lines: \begin{code} @@ -553,7 +591,7 @@ even if you have only the PDF file. \subsection{Translations of keywords}\label{subsect:translation} With \mycmd{\DeclareExamTranslation} you can define the translaitons of the keywords -in an \mypkg{randexam} paper. At this time only English keywords are defined: +in a \mypkg{randexam} paper. \begin{code} \DeclareExamTranslation{english}{ @@ -579,7 +617,9 @@ in an \mypkg{randexam} paper. At this time only English keywords are defined: } \end{code} -You could translate them for another language and enable them with \mycmd{\SelectExamTranslation} command: +At this time only English and Chinese keywords are defined. +You could translate them for another language and enable them +with \mycmd{\SelectExamTranslation} command: \begin{code} \DeclareExamTranslation{somelang}{ @@ -613,21 +653,53 @@ This command is useful in defining new templates for the exam (see Subsection \r \subsection{Saving and reading key values} -With \mycmd{\DeclareExamValue} and \mycmd{\UseExamValue} you could save and read +With \mycmd{\SetExamValue} and \mycmd{\UseExamValue} you could save and read the value of a key, respectively. \begin{code} -\DeclareExamValue{somemodule}{somekey}{SomeValue} +\SetExamValue{somemodule}{somekey=SomeValue} \UseExamValue{somemodule}{somekey} \end{code} \hrule -\DeclareExamValue{somemodule}{somekey}{SomeValue} +\SetExamValue{somemodule}{somekey=SomeValue} \UseExamValue{somemodule}{somekey} \vspace{0.5em} \hrule \vspace{0.5em} -These two commands are useful in defining new templates +The \mypkg{randexam} class also provides commands \mycmd{\IfExamValueExistT}, +\mycmd{\IfExamValueExistF}, and \mycmd{\IfExamValueExistTF}, +with which you can do conditional typesetting. + +\begin{code} +\IfExamValueExistTF{somemodule}{somekey}{True}{False} +\end{code} +\hrule +\IfExamValueExistTF{somemodule}{somekey}{True}{False} +\vspace{0.5em} +\hrule +\vspace{0.5em} + +Furthermore, you may change typeset command of some counter with \mycmd{\SetExamValue} +and the counter is typeset with \mycmd{\TheExamCounter} command when needed. + +\setcounter{exampart}{4} +\begin{code} +\SetExamValue{exampart}{number=\Roman} +\SetExamValue{question}{number=\arabic} +Part \TheExamCounter{exampart}, +Question \TheExamCounter{question} +\end{code} +\hrule +\SetExamValue{exampart}{number=\Roman} +\SetExamValue{question}{number=\arabic} +Part \TheExamCounter{exampart}, +Question \TheExamCounter{question} +\vspace{0.5em} +\hrule +\vspace{0.5em} + +These commands are useful in defining new templates for the exam (see Subsection \ref{subsect:template}). \subsection{Templates of elements}\label{subsect:template} @@ -657,10 +729,10 @@ you can write the following code in document preamble: Then the \mycmd{\examtitle} command in document body will produce different result: \begin{code} -\examtitle{name=Final Exam in My School,date=2024-01-01} +\examtitle{name=Final Exam in My School,date=\today} \end{code} \vspace{-1em} -\examtitle{name=Final Exam in My School,date=2024-01-01} +\examtitle{name=Final Exam in My School,date=\today} Normally \mycmd{\examtitle} will call \mycmd{\UseExamTemplate{examtitle}{default}}. diff --git a/macros/latex/contrib/tagpdf/README.md b/macros/latex/contrib/tagpdf/README.md index b64c5a23fa..96a566d03f 100644 --- a/macros/latex/contrib/tagpdf/README.md +++ b/macros/latex/contrib/tagpdf/README.md @@ -1,6 +1,6 @@ #tagpdf — A package to create tagged pdf -Packageversion: 0.98t -Packagedate: 2024/01/26 +Packageversion: 0.98u +Packagedate: 2024/02/02 Author: Ulrike Fischer, LaTeX Project Team ## License diff --git a/macros/latex/contrib/tagpdf/ex-AF-file.pdf b/macros/latex/contrib/tagpdf/ex-AF-file.pdf index 8837751559..facd2a1003 100644 --- a/macros/latex/contrib/tagpdf/ex-AF-file.pdf +++ b/macros/latex/contrib/tagpdf/ex-AF-file.pdf @@ -1,11 +1,11 @@ %PDF-2.0 % 24 0 obj -<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<> /Length 151 >> +<< /Subtype /application#2Fx-tex/Type /EmbeddedFile /Params<> /Length 151 >> stream %% LaTeX2e file `example-input-file.tex' %% generated by the `filecontents' environment -%% from source `ex-AF-file' on 2024/01/26. +%% from source `ex-AF-file' on 2024/02/02. %% Additional info! @@ -15,7 +15,7 @@ endobj << /Type /Filespec /AFRelationship /Unspecified /F /UF /EF<> >> endobj 27 0 obj -<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<> /Length 19 >> +<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<> /Length 19 >> stream Bär with teh shirt endstream @@ -24,7 +24,7 @@ endobj << /Type /Filespec /AFRelationship /Supplement /F /UF /EF<> >> endobj 30 0 obj -<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<> /Length 4 >> +<< /Subtype /text#2Fplain/Type /EmbeddedFile /Params<> /Length 4 >> stream Duck endstream @@ -242,17 +242,17 @@ stream - 2024-01-26T20:58:41+01:00 + 2024-02-02T22:37:03+01:00 application/pdf ex-AF-file.tex LaTeX - 2024-01-26T20:58:41+01:00 - 2024-01-26T20:58:41+01:00 - 2024-01-26T20:58:41+01:00 + 2024-02-02T22:37:03+01:00 + 2024-02-02T22:37:03+01:00 + 2024-02-02T22:37:03+01:00 uuid:38d5a844-2217-4081-87cc-b2129dc357a6 - uuid:cb6cb011-153d-4b72-827d-6e20f4822861 + uuid:35738719-0a61-4db5-8394-388b6fc161c2 three 1 @@ -353,7 +353,7 @@ endobj << /Type /Namespace /NS (https://www.latex-project.org/ns/inline/2022) /RoleMapNS 20 0 R >> endobj 21 0 obj -<< /Type /Namespace /NS (data:,D665C3A0-56E-F551-A3B2-53B32DA0C704) >> +<< /Type /Namespace /NS (data:,80B08CC2-52D3-4573-44F2-3D24ADA50C43) >> endobj 8 0 obj [ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 21 0 R ] @@ -455,7 +455,7 @@ endobj << /Type /Catalog /Pages 38 0 R /MarkInfo 39 0 R/Lang (de-DE)/Metadata 33 0 R/StructTreeRoot 5 0 R >> endobj 48 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126205841+01'00')/ModDate (D:20240126205841+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223703+01'00')/ModDate (D:20240202223703+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 49 @@ -464,10 +464,10 @@ xref 0000000003 00000 f 0000000004 00000 f 0000000010 00000 f -0000016877 00000 n +0000016878 00000 n 0000013795 00000 n 0000014006 00000 n -0000016300 00000 n +0000016301 00000 n 0000014616 00000 n 0000000012 00000 f 0000014684 00000 n @@ -482,34 +482,34 @@ xref 0000015902 00000 n 0000016212 00000 n 0000000000 00000 f -0000016368 00000 n +0000016369 00000 n 0000000020 00000 n 0000000382 00000 n -0000016481 00000 n +0000016482 00000 n 0000000673 00000 n 0000000828 00000 n -0000016613 00000 n +0000016614 00000 n 0000001062 00000 n 0000001202 00000 n -0000016745 00000 n +0000016746 00000 n 0000001436 00000 n 0000013649 00000 n 0000013514 00000 n 0000012908 00000 n -0000020630 00000 n -0000020984 00000 n +0000020631 00000 n +0000020985 00000 n 0000013759 00000 n 0000013852 00000 n 0000013969 00000 n -0000016997 00000 n -0000019446 00000 n -0000017183 00000 n -0000019667 00000 n -0000020784 00000 n -0000021046 00000 n -0000021164 00000 n +0000016998 00000 n +0000019447 00000 n +0000017184 00000 n +0000019668 00000 n +0000020785 00000 n +0000021047 00000 n +0000021165 00000 n trailer -<< /Size 49 /Root 47 0 R /Info 48 0 R /ID [ <6706A7F57FA2E57B6F29C1F4593BA810> <6706A7F57FA2E57B6F29C1F4593BA810> ] >> +<< /Size 49 /Root 47 0 R /Info 48 0 R /ID [ <6F6CBA95E6A18A300BD05105D2CD9FCD> <6F6CBA95E6A18A300BD05105D2CD9FCD> ] >> startxref -21387 +21388 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf index d2277fd590..5eedeb7ad7 100644 Binary files a/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf and b/macros/latex/contrib/tagpdf/ex-alt-actualtext.pdf differ diff --git a/macros/latex/contrib/tagpdf/ex-attribute.pdf b/macros/latex/contrib/tagpdf/ex-attribute.pdf index 406dff191a..10b045a81f 100644 --- a/macros/latex/contrib/tagpdf/ex-attribute.pdf +++ b/macros/latex/contrib/tagpdf/ex-attribute.pdf @@ -216,17 +216,17 @@ stream - 2024-01-26T20:59:27+01:00 + 2024-02-02T22:37:47+01:00 application/pdf ex-attribute.tex LaTeX - 2024-01-26T20:59:27+01:00 - 2024-01-26T20:59:27+01:00 - 2024-01-26T20:59:27+01:00 + 2024-02-02T22:37:47+01:00 + 2024-02-02T22:37:47+01:00 + 2024-02-02T22:37:47+01:00 uuid:7a9cf910-1c19-429a-8f24-339c62d8a57f - uuid:12b1f461-45c8-435e-80aa-5198be5aa29c + uuid:c0469dea-fd9d-4931-8af5-216a0c68dd97 three 1 @@ -449,7 +449,7 @@ endobj << /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (de_DE)/Metadata 21 0 R/StructTreeRoot 5 0 R >> endobj 38 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20240126205927+01'00')/ModDate (D:20240126205927+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/Title (Title)/CreationDate (D:20240202223747+01'00')/ModDate (D:20240202223747+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 39 @@ -493,7 +493,7 @@ xref 0000017720 00000 n 0000017838 00000 n trailer -<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ ] >> +<< /Size 39 /Root 37 0 R /Info 38 0 R /ID [ <8C22E391CF2CF1A629F3902F8E80CCA6> <8C22E391CF2CF1A629F3902F8E80CCA6> ] >> startxref 18075 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf index 0643e84ff8..cea631691f 100644 --- a/macros/latex/contrib/tagpdf/ex-formula-problem.pdf +++ b/macros/latex/contrib/tagpdf/ex-formula-problem.pdf @@ -239,17 +239,17 @@ stream - 2024-01-26T20:59:50+01:00 + 2024-02-02T22:38:11+01:00 application/pdf ex-formula-problem.tex LaTeX - 2024-01-26T20:59:50+01:00 - 2024-01-26T20:59:50+01:00 - 2024-01-26T20:59:50+01:00 + 2024-02-02T22:38:11+01:00 + 2024-02-02T22:38:11+01:00 + 2024-02-02T22:38:11+01:00 uuid:8eb2ce1d-b2ec-440a-8bc2-73733eb3eeb0 - uuid:8970d22a-9e9e-4862-8221-c3ee6d0d9161 + uuid:3fe0c564-0449-48d0-8aff-fb9f5180667e three 2 @@ -425,7 +425,7 @@ endobj << /Type /Catalog /Pages 16 0 R /MarkInfo 23 0 R/Lang (de-DE)/Metadata 19 0 R/StructTreeRoot 5 0 R >> endobj 33 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126205950+01'00')/ModDate (D:20240126205950+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223811+01'00')/ModDate (D:20240202223811+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 34 @@ -464,7 +464,7 @@ xref 0000018886 00000 n 0000019004 00000 n trailer -<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <32DDD7A2A657D8573D42BD4BCB00A9DA> <32DDD7A2A657D8573D42BD4BCB00A9DA> ] >> +<< /Size 34 /Root 32 0 R /Info 33 0 R /ID [ <63C41E7BFC8B747AC184EC4B36B85829> <63C41E7BFC8B747AC184EC4B36B85829> ] >> startxref 19227 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-list.pdf b/macros/latex/contrib/tagpdf/ex-list.pdf index ca3ab0e31a..c1fededd62 100644 --- a/macros/latex/contrib/tagpdf/ex-list.pdf +++ b/macros/latex/contrib/tagpdf/ex-list.pdf @@ -210,17 +210,17 @@ stream - 2024-01-26T21:00:13+01:00 + 2024-02-02T22:38:38+01:00 application/pdf ex-list.tex LaTeX - 2024-01-26T21:00:13+01:00 - 2024-01-26T21:00:13+01:00 - 2024-01-26T21:00:13+01:00 + 2024-02-02T22:38:38+01:00 + 2024-02-02T22:38:38+01:00 + 2024-02-02T22:38:38+01:00 uuid:4c749825-1de7-414c-879f-29e4d0bef66e - uuid:90b2a6de-94c7-4075-807e-0b97e2163383 + uuid:5c417fb7-2a48-492e-8eee-ce0a6be433ad three 1 @@ -653,7 +653,7 @@ endobj << /Type /Catalog /Pages 54 0 R /MarkInfo 55 0 R/Lang (en-US)/Metadata 48 0 R/StructTreeRoot 5 0 R >> endobj 72 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210013+01'00')/ModDate (D:20240126210013+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223838+01'00')/ModDate (D:20240202223838+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 73 @@ -731,7 +731,7 @@ xref 0000029592 00000 n 0000029710 00000 n trailer -<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ ] >> +<< /Size 73 /Root 71 0 R /Info 72 0 R /ID [ <2EE8B5792D28A5F75A1DF4D2AA3E2581> <2EE8B5792D28A5F75A1DF4D2AA3E2581> ] >> startxref 29933 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf index b751a6d102..2379e8ca20 100644 --- a/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf +++ b/macros/latex/contrib/tagpdf/ex-mc-manual-para-split-obsolete.pdf @@ -243,17 +243,17 @@ stream - 2024-01-26T21:00:34+01:00 + 2024-02-02T22:38:58+01:00 application/pdf ex-mc-manual-para-split-obsolete.tex LaTeX - 2024-01-26T21:00:34+01:00 - 2024-01-26T21:00:34+01:00 - 2024-01-26T21:00:34+01:00 + 2024-02-02T22:38:58+01:00 + 2024-02-02T22:38:58+01:00 + 2024-02-02T22:38:58+01:00 uuid:c33d64b4-96ec-4e48-8f27-0b3edc831547 - uuid:e3b2c8ed-e8fb-46b6-849f-75fd38b47579 + uuid:e15069c5-de84-46d1-81d0-284e5e7b5202 three 2 @@ -413,7 +413,7 @@ endobj << /Type /Catalog /Pages 14 0 R /Lang (en-US)/Metadata 15 0 R >> endobj 25 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210034+01'00')/ModDate (D:20240126210034+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223858+01'00')/ModDate (D:20240202223858+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 26 @@ -444,7 +444,7 @@ xref 0000023897 00000 n 0000023978 00000 n trailer -<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ ] >> +<< /Size 26 /Root 24 0 R /Info 25 0 R /ID [ ] >> startxref 24201 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf index 95b1b31c08..31c494f059 100644 --- a/macros/latex/contrib/tagpdf/ex-softhyphen.pdf +++ b/macros/latex/contrib/tagpdf/ex-softhyphen.pdf @@ -210,17 +210,17 @@ stream - 2024-01-26T21:00:53+01:00 + 2024-02-02T22:39:19+01:00 application/pdf ex-softhyphen.tex LaTeX - 2024-01-26T21:00:53+01:00 - 2024-01-26T21:00:53+01:00 - 2024-01-26T21:00:53+01:00 + 2024-02-02T22:39:19+01:00 + 2024-02-02T22:39:19+01:00 + 2024-02-02T22:39:19+01:00 uuid:aa82e685-4098-469d-861c-3c45dfc700c7 - uuid:8e3f9973-ca76-4bb0-885c-c462a238d3e9 + uuid:ff06d09b-d1ff-4746-88cb-913348b6bed3 three 1 @@ -393,7 +393,7 @@ endobj << /Type /Catalog /Pages 19 0 R /MarkInfo 20 0 R/Lang (en-US)/Metadata 14 0 R/StructTreeRoot 5 0 R >> endobj 30 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210053+01'00')/ModDate (D:20240126210053+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223919+01'00')/ModDate (D:20240202223919+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 31 @@ -429,7 +429,7 @@ xref 0000018116 00000 n 0000018234 00000 n trailer -<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <5861020C59C64EDB711834443873AFAC> <5861020C59C64EDB711834443873AFAC> ] >> +<< /Size 31 /Root 29 0 R /Info 30 0 R /ID [ <0E4E2750E80EA2B652B1FB8967503A62> <0E4E2750E80EA2B652B1FB8967503A62> ] >> startxref 18457 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf index 360b5fd2cf..1e31c89cfd 100644 --- a/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf +++ b/macros/latex/contrib/tagpdf/ex-spaceglyph-listings.pdf @@ -210,17 +210,17 @@ stream - 2024-01-26T21:01:12+01:00 + 2024-02-02T22:39:39+01:00 application/pdf ex-spaceglyph-listings.tex LaTeX - 2024-01-26T21:01:12+01:00 - 2024-01-26T21:01:12+01:00 - 2024-01-26T21:01:12+01:00 + 2024-02-02T22:39:39+01:00 + 2024-02-02T22:39:39+01:00 + 2024-02-02T22:39:39+01:00 uuid:acdc2435-bf29-4e54-8d09-1c9b6dc32038 - uuid:2da7c0a8-0aad-46d2-8e28-b7f2a1930d27 + uuid:106cffe6-9e83-4343-875e-bf36e39202e9 three 1 @@ -354,7 +354,7 @@ endobj << /Type /Catalog /Pages 15 0 R /MarkInfo 16 0 R/Lang (en-US)/Metadata 10 0 R/StructTreeRoot 5 0 R >> endobj 26 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210112+01'00')/ModDate (D:20240126210112+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223939+01'00')/ModDate (D:20240202223939+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 27 @@ -386,7 +386,7 @@ xref 0000015484 00000 n 0000015602 00000 n trailer -<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <4D137DF5E094011AB5CF6EF03BFCCE2C> <4D137DF5E094011AB5CF6EF03BFCCE2C> ] >> +<< /Size 27 /Root 25 0 R /Info 26 0 R /ID [ <0FFF207E4920BBD2110B159C2D9324F6> <0FFF207E4920BBD2110B159C2D9324F6> ] >> startxref 15825 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf index 7ba830979b..d74c03578f 100644 --- a/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf +++ b/macros/latex/contrib/tagpdf/ex-structure-obsolete.pdf @@ -210,17 +210,17 @@ stream - 2024-01-26T21:01:31+01:00 + 2024-02-02T22:39:59+01:00 application/pdf ex-structure-obsolete.tex LaTeX - 2024-01-26T21:01:31+01:00 - 2024-01-26T21:01:31+01:00 - 2024-01-26T21:01:31+01:00 + 2024-02-02T22:39:59+01:00 + 2024-02-02T22:39:59+01:00 + 2024-02-02T22:39:59+01:00 uuid:bf5e4a2b-cfa9-4fc5-878c-8f9d2ee95445 - uuid:58915d1b-721c-4e2f-8b60-999570652301 + uuid:10235932-5d34-48f2-81ce-e522f266d343 three 1 @@ -526,7 +526,7 @@ endobj << /Type /Catalog /Pages 26 0 R /MarkInfo 27 0 R/Lang (en-US)/Metadata 20 0 R/StructTreeRoot 5 0 R >> endobj 43 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210131+01'00')/ModDate (D:20240126210131+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202223959+01'00')/ModDate (D:20240202223959+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 44 @@ -575,7 +575,7 @@ xref 0000023426 00000 n 0000023544 00000 n trailer -<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <7E9B742ACCDBAEA64E0D4254DB9A148F> <7E9B742ACCDBAEA64E0D4254DB9A148F> ] >> +<< /Size 44 /Root 42 0 R /Info 43 0 R /ID [ <1E58A57ED576731A14E6B7847804E1C7> <1E58A57ED576731A14E6B7847804E1C7> ] >> startxref 23767 %%EOF diff --git a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf index 476a154f58..6dc444340a 100644 --- a/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf +++ b/macros/latex/contrib/tagpdf/ex-tagpdf-template.pdf @@ -210,17 +210,17 @@ stream - 2024-01-26T21:01:51+01:00 + 2024-02-02T22:40:21+01:00 application/pdf ex-tagpdf-template.tex LaTeX - 2024-01-26T21:01:51+01:00 - 2024-01-26T21:01:51+01:00 - 2024-01-26T21:01:51+01:00 + 2024-02-02T22:40:21+01:00 + 2024-02-02T22:40:21+01:00 + 2024-02-02T22:40:21+01:00 uuid:f320abfc-f6ab-4d12-8719-d176f4d947cf - uuid:a21419d2-023c-4512-8135-0ae4ab36b4bd + uuid:e9c2bc0c-c443-48b5-8ced-b99f15ae41a0 three 1 @@ -312,7 +312,7 @@ endobj << /Type /Namespace /NS (https://www.latex-project.org/ns/inline/2022) /RoleMapNS 20 0 R >> endobj 21 0 obj -<< /Type /Namespace /NS (data:,B029B424-4166-87C8-F620-397B784D410C) >> +<< /Type /Namespace /NS (data:,D77936FE-8-5FAE-4338-D9DD76B7C691) >> endobj 8 0 obj [ 9 0 R 11 0 R 13 0 R 15 0 R 17 0 R 19 0 R 21 0 R ] @@ -404,7 +404,7 @@ endobj << /Type /Catalog /Pages 33 0 R /MarkInfo 34 0 R/Lang (en-US)/Metadata 28 0 R/StructTreeRoot 5 0 R >> endobj 44 0 obj -<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240126210151+01'00')/ModDate (D:20240126210151+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> +<< /Producer (luahbtex-1.17.0)/Creator (LaTeX)/CreationDate (D:20240202224021+01'00')/ModDate (D:20240202224021+01'00') /Trapped /False /PTEX.FullBanner (This is LuaHBTeX, Version 1.17.0 (TeX Live 2023)) >> endobj xref 0 45 @@ -413,10 +413,10 @@ xref 0000000003 00000 f 0000000004 00000 f 0000000010 00000 f -0000015155 00000 n +0000015152 00000 n 0000012015 00000 n 0000012225 00000 n -0000014583 00000 n +0000014580 00000 n 0000012898 00000 n 0000000012 00000 f 0000012966 00000 n @@ -431,30 +431,30 @@ xref 0000014184 00000 n 0000014494 00000 n 0000000000 00000 f -0000014651 00000 n -0000014748 00000 n -0000014835 00000 n -0000014922 00000 n -0000015021 00000 n +0000014648 00000 n +0000014745 00000 n +0000014832 00000 n +0000014919 00000 n +0000015018 00000 n 0000000020 00000 n 0000011869 00000 n 0000011734 00000 n 0000011500 00000 n -0000017776 00000 n -0000018130 00000 n +0000017773 00000 n +0000018127 00000 n 0000011979 00000 n 0000012056 00000 n 0000012188 00000 n 0000012835 00000 n -0000015292 00000 n -0000016733 00000 n -0000015379 00000 n -0000016954 00000 n -0000017930 00000 n -0000018192 00000 n -0000018310 00000 n +0000015289 00000 n +0000016730 00000 n +0000015376 00000 n +0000016951 00000 n +0000017927 00000 n +0000018189 00000 n +0000018307 00000 n trailer -<< /Size 45 /Root 43 0 R /Info 44 0 R /ID [ ] >> +<< /Size 45 /Root 43 0 R /Info 44 0 R /ID [ ] >> startxref -18533 +18530 %%EOF diff --git a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx index 809fb896fc..811da15758 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-backend.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-backend.dtx @@ -47,13 +47,13 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*luatex> -\ProvidesExplFile {tagpdf-luatex.def} {2024-01-26} {0.98t} +\ProvidesExplFile {tagpdf-luatex.def} {2024-02-02} {0.98u} {tagpdf~driver~for~luatex} % \end{macrocode} % \section{Loading the lua} @@ -158,8 +158,8 @@ local ProvidesLuaModule = { name = "tagpdf", - version = "0.98t", --TAGVERSION - date = "2024-01-26", --TAGDATE + version = "0.98u", --TAGVERSION + date = "2024-02-02", --TAGDATE description = "tagpdf lua code", license = "The LATEX Project Public License 1.3c" } diff --git a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx index 5205df1cf6..83586fb20c 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-checks.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-checks.dtx @@ -48,7 +48,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \section{Commands} @@ -327,7 +327,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-checks-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-checks-code} {2024-02-02} {0.98u} {part of tagpdf - code related to checks, conditionals, debugging and messages} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-code.pdf b/macros/latex/contrib/tagpdf/tagpdf-code.pdf index 67914b3a80..6cb075911a 100644 Binary files a/macros/latex/contrib/tagpdf/tagpdf-code.pdf and b/macros/latex/contrib/tagpdf/tagpdf-code.pdf differ diff --git a/macros/latex/contrib/tagpdf/tagpdf-data.dtx b/macros/latex/contrib/tagpdf/tagpdf-data.dtx index e9f0d14790..6405215297 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-data.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-data.dtx @@ -47,7 +47,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % This files contains a various data files which are read in @@ -60,7 +60,7 @@ % It lists the new tag, the rolemap and the namespace of the rolemap. % \begin{macrocode} %<*ns-latex> -%% \ProvidesExplFile {tagpdf-ns-latex.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-latex.def} {2024-02-02} {0.98u} %% {latex} {https://www.latex-project.org/ns/dflt/2022}{} title, Title, pdf2, part, Title, pdf2, @@ -92,7 +92,7 @@ text, P, pdf2, % It is bound to change % \begin{macrocode} %<*ns-latex-book> -%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-latex-book.def} {2024-02-02} {0.98u} %% {latex-book} {https://www.latex-project.org/ns/book/2022}{} chapter, H1,pdf2, section, H2,pdf2, @@ -108,7 +108,7 @@ subparagraph, H6,pdf2, % loaded. % \begin{macrocode} %<*ns-latex-inline> -%% \ProvidesExplFile {tagpdf-ns-latex-inline.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-latex-inline.def} {2024-02-02} {0.98u} %% {latex-inline} {https://www.latex-project.org/ns/inline/2022}{} chapter, Span, pdf2, section, Span, pdf2, @@ -122,7 +122,7 @@ P, Span, pdf2, % \section{The pdf namespace data} % \begin{macrocode} %<*ns-pdf> -%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-pdf.def} {2024-02-02} {0.98u} %% {pdf} {http://iso.org/pdf/ssn}{} StructTreeRoot,StructTreeRoot,pdf,D, Document,Document,pdf,D, @@ -190,7 +190,7 @@ Strong,Span,pdf,I, % \section{The pdf 2.0 namespace data} % \begin{macrocode} %<*ns-pdf2> -%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-pdf2.def} {2024-02-02} {0.98u} %% {pdf2} {http://iso.org/pdf2/ssn}{} StructTreeRoot,StructTreeRoot,pdf2,D, Document,Document,pdf2,D, @@ -247,7 +247,7 @@ Strong,Strong,pdf2,I, % \section{The mathml namespace data} % \begin{macrocode} %<*ns-mathml> -%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-ns-mathml.def} {2024-02-02} {0.98u} % {mathml}{http://www.w3.org/1998/Math/MathML}{} abs,abs,mathml, and,and,mathml, @@ -482,7 +482,7 @@ xor,xor,mathml, % This will perhaps change in future. % \begin{macrocode} %<*parent-child> -%% \ProvidesExplFile {tagpdf-parent-child.csv} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-parent-child.csv} {2024-02-02} {0.98u} ,,,StructTreeRoot,Document,Art,Part,Div,Sect,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,MC Document,both,document level,1,0..n,∅,‡,‡,∅,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅ Art,1.7,grouping,∅,0..n,∅,‡,‡,0..n,0..n,‡,∅,∅,∅,0..n,∅,0..n,∅,∅,∅,0..1,0..1,∅,∅,∅,0..n,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅,∅,0..n,0..n,∅,∅,∅,0..n,0..n,∅,∅ @@ -537,7 +537,7 @@ MC,both,---,∅,∅,∅,∅,∅,∅,0..n,‡,∅,∅,∅,0..n,0..n,0..n,0..n,0.. % This will perhaps change in future. % \begin{macrocode} %<*parent-child-2> -%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2024-01-26} {0.98t} +%% \ProvidesExplFile {tagpdf-parent-child-2.csv} {2024-02-02} {0.98u} ,,,StructTreeRoot,Document,DocumentFragment,Art,Part,Div,Sect,Aside,BlockQuote,NonStruct,TOC,TOCI,Index,Private,Title,Sub,Quote,Note,Reference,BibEntry,P,Hn,H,Lbl,Code,Em,Strong,Span,Link,Annot,Form,Ruby,RB,RT,RP,Warichu,WT,WP,FENote,L,LI,LBody,Table,TR,TH,TD,THead,TBody,TFoot,Caption,Figure,Formula,math,mathml,Artifact,MC Document,both,document level,1,0..n,0..n,∅,‡,‡,∅,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,0..n,∅ DocumentFragment,2.0,document level,∅,0..n,0..n,0..n,‡,‡,0..n,0..n,0..n,‡,∅,∅,∅,0..n,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅*,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅,∅*,∅,∅,∅,∅,0..n,∅ diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx index 3764e92d11..04f5501657 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-generic.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \end{documentation} @@ -55,11 +55,11 @@ % \begin{macrocode} %<@@=tag> %<*generic> -\ProvidesExplPackage {tagpdf-mc-code-generic} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-mc-code-generic} {2024-02-02} {0.98u} {part of tagpdf - code related to marking chunks - generic mode} % %<*debug> -\ProvidesExplPackage {tagpdf-debug-generic} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-debug-generic} {2024-02-02} {0.98u} {part of tagpdf - debugging code related to marking chunks - generic mode} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx index 20dd45ecc2..8f9678e55a 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-luacode.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{implementation} % The code is splitted into three parts: code shared by all engines, @@ -86,11 +86,11 @@ % \begin{macrocode} %<@@=tag> %<*luamode> -\ProvidesExplPackage {tagpdf-mc-code-lua} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-mc-code-lua} {2024-02-02} {0.98u} {tagpdf - mc code only for the luamode } % %<*debug> -\ProvidesExplPackage {tagpdf-debug-lua} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-debug-lua} {2024-02-02} {0.98u} {part of tagpdf - debugging code related to marking chunks - lua mode} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx index db7c727770..8799df3d4c 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-mc-shared.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -181,7 +181,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-mc-code-shared} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-mc-code-shared} {2024-02-02} {0.98u} {part of tagpdf - code related to marking chunks - code shared by generic and luamode } % diff --git a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx index 682c4e387a..98750fa461 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-roles.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-roles.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \begin{function} @@ -98,7 +98,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-roles-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-roles-code} {2024-02-02} {0.98u} {part of tagpdf - code related to roles and structure names} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-space.dtx b/macros/latex/contrib/tagpdf/tagpdf-space.dtx index feff45c173..3e3b3de7e6 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-space.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-space.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \begin{function}{interwordspace (setup-key)} @@ -64,7 +64,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-space-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-space-code} {2024-02-02} {0.98u} {part of tagpdf - code related to real space chars} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx index bcc9083ae2..8f0dd1e717 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-struct.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-struct.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \section{Public Commands} @@ -285,7 +285,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-struct-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-struct-code} {2024-02-02} {0.98u} {part of tagpdf - code related to storing structure} % % \end{macrocode} @@ -1905,7 +1905,7 @@ % \section{Attributes and attribute classes} % \begin{macrocode} %<*header> -\ProvidesExplPackage {tagpdf-attr-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-attr-code} {2024-02-02} {0.98u} {part of tagpdf - code related to attributes and attribute classes} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx index 362f3ecf7e..d9ed68f31f 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-tree.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-tree.dtx @@ -47,13 +47,13 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{implementation} % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-tree-code} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-tree-code} {2024-02-02} {0.98u} {part of tagpdf - code related to writing trees and dictionaries to the pdf} % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf-user.dtx b/macros/latex/contrib/tagpdf/tagpdf-user.dtx index ebdc8cece2..aea543ba40 100644 --- a/macros/latex/contrib/tagpdf/tagpdf-user.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf-user.dtx @@ -46,7 +46,7 @@ % }^^A % } % -% \date{Version 0.98t, released 2024-01-26} +% \date{Version 0.98u, released 2024-02-02} % \maketitle % \begin{documentation} % \section{Setup commands} @@ -303,7 +303,7 @@ % \begin{macrocode} %<@@=tag> %<*header> -\ProvidesExplPackage {tagpdf-user} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-user} {2024-02-02} {0.98u} {tagpdf - user commands} % % \end{macrocode} @@ -736,6 +736,7 @@ % \g_@@_para_end_int, % \g_@@_para_main_begin_int, % \g_@@_para_main_end_int, +% \g_@@_para_main_struct_tl, % \l_@@_para_tag_default_tl, % \l_@@_para_tag_tl, % \l_@@_para_main_tag_tl, @@ -752,6 +753,10 @@ \int_new:N \g_@@_para_end_int \int_new:N \g_@@_para_main_begin_int \int_new:N \g_@@_para_main_end_int +% \end{macrocode} +% this will hold the structure number of the current text-unit. +% \begin{macrocode} +\tl_new:N \g_@@_para_main_struct_tl \tl_new:N \l_@@_para_tag_default_tl \tl_set:Nn \l_@@_para_tag_default_tl { text } \tl_new:N \l_@@_para_tag_tl @@ -795,7 +800,6 @@ } % \end{macrocode} % \end{macro} - % \begin{macro}{\@@_start_para_ints:,\@@_stop_para_ints:} % \begin{macrocode} \cs_new_protected:Npn \@@_start_para_ints: @@ -827,21 +831,31 @@ % \end{macrocode} % \end{macro} % +% We want to be able to inspect the current para main structure, so +% we need a command to store its structure number +% \begin{macro}{\@@_para_main_store_struct:} +% \begin{macrocode} +\cs_new:Npn \@@_para_main_store_struct: + { + \tl_gset:Ne \g_@@_para_main_struct_tl {\int_use:N \c@g_@@_struct_abs_int } + } +% \end{macrocode} +% \end{macro} % TEMPORARLY FIX (2023-11-17). Until latex-lab is updated we must adapt a sec command: % \begin{macrocode} \AddToHook{package/latex-lab-testphase-sec/after} { \cs_set_protected:Npn \@kernel@tag@hangfrom #1 { - \tagstructbegin{tag=\l__tag_para_tag_tl} - \__tag_gincr_para_begin_int: + \tagstructbegin{tag=\l_@@_para_tag_tl} + \@@_gincr_para_begin_int: \tagstructbegin{tag=Lbl} \setbox\@tempboxa \hbox { \bool_lazy_and:nnT {\tag_if_active_p:} - {\g__tag_mode_lua_bool} + {\g_@@_mode_lua_bool} {\tagmcbegin{tag=Lbl}} {#1} } @@ -852,7 +866,7 @@ } } % \end{macrocode} -% and two adaptions from the block module: +% and one temporary adaptions for the block module: % \begin{macrocode} \AddToHook{package/latex-lab-testphase-block/after} { @@ -860,49 +874,6 @@ { \tl_set:Nn \l_@@_para_attr_class_tl { \l_tag_para_attr_class_tl } } - \cs_set_protected:Npn \__block_start_para_structure:n #1 { - \__block_debug_typeout:n - { @endpe = \legacy_if:nTF { @endpe }{true}{false} - \on@line } - \legacy_if:nF { @endpe } - { - \bool_if:NF \l__tag_para_flattened_bool - { - \@@_gincr_para_main_begin_int: - \tag_struct_begin:n - { - tag=\l_@@_para_main_tag_tl, - attribute-class=\l_@@_para_main_attr_class_tl, - } - } - } - \@@_gincr_para_begin_int: - \__block_debug_typeout:n{increment~ P \on@line } - \tag_struct_begin:n - { - tag=\l__tag_para_tag_tl - ,attribute-class=\l_@@_para_attr_class_tl - } - \__tag_check_para_begin_show:nn {green}{#1} - \tag_mc_begin:n {} - } - \RemoveFromHook{para/end}[latex-lab-testphase-block] - \AddToHook{para/end}[latex-lab-testphase-block] - { - \bool_if:NT \l__tag_para_bool - { - \__tag_gincr_para_end_int: - \__block_debug_typeout:n{increment~ /P \on@line } - \tag_mc_end: - \__tag_check_para_end_show:nn {red}{} - \tag_struct_end: - \bool_if:NF \l__tag_para_flattened_bool - { - \__tag_gincr_para_main_end_int: - \tag_struct_end: - } - } - } } % \end{macrocode} @@ -934,7 +905,7 @@ } % \end{macrocode} % \end{macro} -% This fills the para hooks with the needed code. +% Helper command for debugging: % \begin{macrocode} \cs_new_protected:Npn \@@_check_para_begin_show:nn #1 #2 %#1 color, #2 prefix @@ -957,30 +928,82 @@ \tag_mc_end: } } - -\AddToHook{para/begin} - { +% \end{macrocode} +% +% The para/begin and para/end code. +% We have two variants here: a simpler one, which must be used +% if the block code is not used (and so probably will disappear +% at some time) and a more sophisticated one that must +% be used if the block code is used. +% It is possible that we will need more variants, so +% we setup a socket so that the code can be easily switched. +% \begin{macrocode} +\socket_new:nn {tagsupport/para/begin}{0} +\socket_new:nn {tagsupport/para/end}{0} + +\socket_new_plug:nnn{tagsupport/para/begin}{plain} + { \bool_if:NT \l_@@_para_bool { \bool_if:NF \l_@@_para_flattened_bool + { + \@@_gincr_para_main_begin_int: + \tag_struct_begin:n + { + tag=\l_@@_para_main_tag_tl, + } + \@@_para_main_store_struct: + } + \@@_gincr_para_begin_int: + \tag_struct_begin:n {tag=\l_@@_para_tag_tl} + \@@_check_para_begin_show:nn {green}{} + \tag_mc_begin:n {} + } + } +\socket_new_plug:nnn{tagsupport/para/begin}{block} + { + \bool_if:NT \l_@@_para_bool + { + \legacy_if:nF { @inlabel } { - \@@_gincr_para_main_begin_int: - \tag_struct_begin:n - { - tag=\l_@@_para_main_tag_tl, + \@@_check_typeout_v:n + {==>~ @endpe = \legacy_if:nTF { @endpe }{true}{false} \on@line } + \legacy_if:nF { @endpe } + { + \bool_if:NF \l_@@_para_flattened_bool + { + \@@_gincr_para_main_begin_int: + \tag_struct_begin:n + { + tag=\l_@@_para_main_tag_tl, + attribute-class=\l_@@_para_main_attr_class_tl, + } + \@@_para_main_store_struct: + } } - } - \@@_gincr_para_begin_int: - \tag_struct_begin:n {tag=\l_@@_para_tag_tl} - \@@_check_para_begin_show:nn {green}{} - \tag_mc_begin:n {} - } - } -\AddToHook{para/end} + \@@_gincr_para_begin_int: + \@@_check_typeout_v:n {==>~increment~ P \on@line } + \tag_struct_begin:n + { + tag=\l_@@_para_tag_tl + ,attribute-class=\l_@@_para_attr_class_tl + } + \@@_check_para_begin_show:nn {green}{\PARALABEL} + \tag_mc_begin:n {} + } + } + } +% \end{macrocode} +% there was no real difference between the original and +% in the block variant, only a debug message. We therefore +% define only a plain variant. +% \begin{macrocode} +\socket_new_plug:nnn{tagsupport/para/end}{plain} { \bool_if:NT \l_@@_para_bool { \@@_gincr_para_end_int: + \@@_check_typeout_v:n {==>~increment~ /P \on@line } \tag_mc_end: \@@_check_para_end_show:nn {red}{} \tag_struct_end: @@ -989,9 +1012,43 @@ \@@_gincr_para_main_end_int: \tag_struct_end: } - } + } } % \end{macrocode} +% By default we assign the plain plug: +% \begin{macrocode} +\socket_assign_plug:nn { tagsupport/para/begin}{plain} +\socket_assign_plug:nn { tagsupport/para/end}{plain} +% \end{macrocode} +% And use the sockets in the hooks. Once tagging sockets exist, this +% can be adapted. +% \begin{macrocode} +\AddToHook{para/begin}{ \socket_use:n { tagsupport/para/begin } + } +\AddToHook{para/end} { \socket_use:n { tagsupport/para/end } } +% \end{macrocode} +% +% If the block code is loaded we must ensure that it doesn't overwrite +% the hook again. And we must reassign the para/begin plug. +% This can go once the block code no longer tries to adapt the hooks. +% \begin{macrocode} +\AddToHook{package/latex-lab-testphase-block/after} + { + \RemoveFromHook{para/begin}[tagpdf] + \RemoveFromHook{para/end}[latex-lab-testphase-block] + \AddToHook{para/begin}[tagpdf] + { + \socket_use:n { tagsupport/para/begin } + } + \AddToHook{para/end}[tagpdf] + { + \socket_use:n { tagsupport/para/end } + } + \socket_assign_plug:nn { tagsupport/para/begin}{block} + } + +% \end{macrocode} +% % We check the para count at the end. If tagging is not active it is not a error, % but we issue a warning as it perhaps indicates that the testphase code didn't guard % everything correctly. diff --git a/macros/latex/contrib/tagpdf/tagpdf.dtx b/macros/latex/contrib/tagpdf/tagpdf.dtx index 71585725aa..d1ccff926c 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.dtx +++ b/macros/latex/contrib/tagpdf/tagpdf.dtx @@ -84,7 +84,7 @@ % \begin{macrocode} %<@@=tag> %<*package> -\ProvidesExplPackage {tagpdf} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf} {2024-02-02} {0.98u} { A package to experiment with pdf tagging } \bool_if:nF @@ -110,7 +110,7 @@ % \end{macrocode} %<*debug> % \begin{macrocode} -\ProvidesExplPackage {tagpdf-debug} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-debug} {2024-02-02} {0.98u} { debug code for tagpdf } \@ifpackageloaded{tagpdf}{}{\PackageWarning{tagpdf-debug}{tagpdf~not~loaded,~quitting}\endinput} % \end{macrocode} @@ -133,7 +133,7 @@ % we define a base package with dummy functions % \begin{macrocode} %<*base> -\ProvidesExplPackage {tagpdf-base} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdf-base} {2024-02-02} {0.98u} {part of tagpdf - provide base, no-op versions of the user commands } % % \end{macrocode} diff --git a/macros/latex/contrib/tagpdf/tagpdf.pdf b/macros/latex/contrib/tagpdf/tagpdf.pdf index 61f0c3e3c3..92d19dd6ff 100644 Binary files a/macros/latex/contrib/tagpdf/tagpdf.pdf and b/macros/latex/contrib/tagpdf/tagpdf.pdf differ diff --git a/macros/latex/contrib/tagpdf/tagpdf.tex b/macros/latex/contrib/tagpdf/tagpdf.tex index 2d9ab2ef1b..0b94e9406f 100644 --- a/macros/latex/contrib/tagpdf/tagpdf.tex +++ b/macros/latex/contrib/tagpdf/tagpdf.tex @@ -16,8 +16,8 @@ } \DebugBlocksOff \makeatletter -\def\UlrikeFischer@package@version{0.98t} -\def\UlrikeFischer@package@date{2024-01-26} +\def\UlrikeFischer@package@version{0.98u} +\def\UlrikeFischer@package@date{2024-02-02} \makeatother \documentclass[bibliography=totoc,a4paper]{article} diff --git a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty index 90418591a0..bc74eb1bc9 100644 --- a/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty +++ b/macros/latex/contrib/tagpdf/tagpdfdocu-patches.sty @@ -1,5 +1,5 @@ %\RequirePackage[enable-debug]{expl3}[2018/06/14] -\ProvidesExplPackage {tagpdfdocu-patches} {2024-01-26} {0.98t} +\ProvidesExplPackage {tagpdfdocu-patches} {2024-02-02} {0.98u} {patches/commands for the tagpdf documentation} \RequirePackage{etoolbox,xpatch} diff --git a/macros/latex/contrib/wargame/README.md b/macros/latex/contrib/wargame/README.md index 3de32ab4d0..70eb286498 100644 --- a/macros/latex/contrib/wargame/README.md +++ b/macros/latex/contrib/wargame/README.md @@ -1,6 +1,6 @@ # A package to make Hex'n'Counter wargames in LaTeX -## Version 0.5 +## Version 0.6 This package can help make classic [Hex'n'Counter wargames](https://en.wikipedia.org/wiki/Wargame) using LaTeX. The diff --git a/macros/latex/contrib/wargame/doc/compat.pdf b/macros/latex/contrib/wargame/doc/compat.pdf index 2ba344d4ab..8f70ab6b2e 100644 Binary files a/macros/latex/contrib/wargame/doc/compat.pdf and b/macros/latex/contrib/wargame/doc/compat.pdf differ diff --git a/macros/latex/contrib/wargame/doc/symbols.pdf b/macros/latex/contrib/wargame/doc/symbols.pdf index cd8f0d3ddc..9722803067 100644 Binary files a/macros/latex/contrib/wargame/doc/symbols.pdf and b/macros/latex/contrib/wargame/doc/symbols.pdf differ diff --git a/macros/latex/contrib/wargame/doc/tutorial/export.tex b/macros/latex/contrib/wargame/doc/tutorial/export.tex index 6d6722d9ac..390b8785ae 100644 --- a/macros/latex/contrib/wargame/doc/tutorial/export.tex +++ b/macros/latex/contrib/wargame/doc/tutorial/export.tex @@ -77,9 +77,9 @@ % counter. % % \begin{macrocode} -\doublechitimages[A]{\alla} -\doublechitimages[B]{\allb} -\doublechitimages[Markers]{{game turn chit}} +\doublechitimages[A][chit drop shadows]{\alla} +\doublechitimages[B][chit drop shadows]{\allb} +\doublechitimages[Markers][chit drop shadows]{{game turn chit}} % \end{macrocode} % % Again, the macros we made for the counters comes in handy. Note @@ -96,7 +96,9 @@ % can.}. % % \begin{macrocode} -\battlemarkers{12} +\tikzset{} +\battlemarkers[marker drop shadows]{12} +\tikzset{every battle marker/.style={}} % \end{macrocode} % % Furthermore, we can add ``odds'' and battle result markers. Odds @@ -108,14 +110,14 @@ % in the markers. % % \begin{macrocode} -\oddsmarkers{% +\oddsmarkers[marker drop shadows]{% 1:3/red!25!white,% 1:2/red!15!white,% 1:1/orange!15!white,% 2:1/white,% 3:1/green!15!white,% 4:1/green!25!white} -\resultmarkers{ +\resultmarkers[marker drop shadows]{ AE/red!50!white, AR/red!25!white, EX/white, diff --git a/macros/latex/contrib/wargame/doc/tutorial/game.pdf b/macros/latex/contrib/wargame/doc/tutorial/game.pdf index f4e8a22e2a..63ea8b0733 100644 Binary files a/macros/latex/contrib/wargame/doc/tutorial/game.pdf and b/macros/latex/contrib/wargame/doc/tutorial/game.pdf differ diff --git a/macros/latex/contrib/wargame/doc/wargame.pdf b/macros/latex/contrib/wargame/doc/wargame.pdf index 01a58c597b..9b608b4144 100644 Binary files a/macros/latex/contrib/wargame/doc/wargame.pdf and b/macros/latex/contrib/wargame/doc/wargame.pdf differ diff --git a/macros/latex/contrib/wargame/source/Makefile b/macros/latex/contrib/wargame/source/Makefile index e11c477bf7..8320c42419 100644 --- a/macros/latex/contrib/wargame/source/Makefile +++ b/macros/latex/contrib/wargame/source/Makefile @@ -2,7 +2,7 @@ # # NAME := wargame -VERSION := 0.5 +VERSION := 0.6 LATEX_FLAGS := -interaction=nonstopmode \ -file-line-error \ --synctex=15 \ diff --git a/macros/latex/contrib/wargame/source/chit/battle.dtx b/macros/latex/contrib/wargame/source/chit/battle.dtx index 5057d620a5..381f4e4aba 100644 --- a/macros/latex/contrib/wargame/source/chit/battle.dtx +++ b/macros/latex/contrib/wargame/source/chit/battle.dtx @@ -41,7 +41,7 @@ minimum size=8mm, draw=black, fill=#2, - every odds marker/.try] at (.2,-.2) {#1}; + every odds marker/.try] at (.16,-.16) {#1}; } }, odds marker/.style args={#1,#2}{ diff --git a/macros/latex/contrib/wargame/source/chit/misc.dtx b/macros/latex/contrib/wargame/source/chit/misc.dtx index a5b9a79b24..e5d4b4b708 100644 --- a/macros/latex/contrib/wargame/source/chit/misc.dtx +++ b/macros/latex/contrib/wargame/source/chit/misc.dtx @@ -4,6 +4,58 @@ % \fi % \subsubsection{Some utilities} % +% This style allows us to add a fading drop-shadow to chits. +% +% \begin{macrocode} +\usetikzlibrary{shadows.blur} +\newif\ifwg@chit@drop\wg@chit@dropfalse +\tikzset{ + chit has drop/.is if=wg@chit@drop, + chit has drop/.default=true, + chit has drop/.initial=false, + /tikz/render blur shadow/.add code={% + \chit@dbg{2}{Number of blur steps: \pgfbs@steps}% + \ifnum\pgfbs@steps=0\else + \chit@dbg{2}{Making shadow blur}% + }{\fi}} +\tikzset{% + chit drop/.code={% + %% \message{^^J Args `#1'}% + \pgfkeysalso{% + chit has drop=true, + /tikz/blur shadow={shadow blur steps=5, + shadow opacity=25, + shadow xshift=.05cm, + shadow yshift=-.05cm, + shadow blur radius=.05cm, + #1}}% + \ifnum\pgfbs@steps=0% + \gdef\wg@drop@margin{0pt}% + \else% + \ifwg@chit@drop% + \pgfmathparse{ + \pgfbs@radius+ + veclen( + \pgfkeysvalueof{/tikz/shadow xshift}, + \pgfkeysvalueof{/tikz/shadow yshift})} + \xdef\wg@drop@margin{\pgfmathresult pt}% + \else% + \gdef\wg@drop@margin{0pt}% + \fi + %% \message{^^J Drop margin is `\wg@drop@margin' + %% `\pgfbs@radius' + %% `\pgfkeysvalueof{/tikz/shadow xshift}', + %% `\pgfkeysvalueof{/tikz/shadow yshift}'}% + \fi% + },% + chit drop/.default=,% + no chit drop/.code={% + \pgfkeysalso{ + /tikz/blur shadow={shadow blur steps=0}} + \gdef\wg@drop@margin{0pt}% + } +}% +% \end{macrocode} % % Game turn marker % diff --git a/macros/latex/contrib/wargame/source/chit/modifiers.dtx b/macros/latex/contrib/wargame/source/chit/modifiers.dtx index b42ee5790f..f2f47ee3a8 100644 --- a/macros/latex/contrib/wargame/source/chit/modifiers.dtx +++ b/macros/latex/contrib/wargame/source/chit/modifiers.dtx @@ -14,7 +14,7 @@ code={% \path[fill=white,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}}, pics/chit/eliminate/.style={ - code={% + code={% \path[fill=red,opacity=#1,pic actions] (-.6,-.6) rectangle(.6,.6);}}, pics/chit/shade/.default=0.5, pics/chit/eliminate/.default=0.25, diff --git a/macros/latex/contrib/wargame/source/chit/oob.dtx b/macros/latex/contrib/wargame/source/chit/oob.dtx index d640dadebf..9e5f0c4f93 100644 --- a/macros/latex/contrib/wargame/source/chit/oob.dtx +++ b/macros/latex/contrib/wargame/source/chit/oob.dtx @@ -37,8 +37,9 @@ \def\chit@oob@rowupdate(#1,#2)#3#4{% \chit@dbg{2}{ Row update c=`#1',r=`#2',s=`#3',e=`#4'} %\pgfmathparse{ifthenelse(#1>0,#2-#3,#2)}% - \pgfmathparse{#2-#3)}% + \pgfmathparse{#2-#3-#4}% \xdef#2{\pgfmathresult}% + \xdef#1{0}%\pgfmathresult}% %\xdef#1{0} \chit@dbg{2}{ \space\space-> update `\string#2'=#2} } @@ -71,6 +72,7 @@ % \begin{macrocode} \newif\ifwg@oob@inv\wg@oob@invfalse \def\chit@oob@spacer{hspace} +\def\chit@oob@vspacer{vspace} \def\wg@star@oob{\wg@oob@invtrue\wg@oob} \def\wg@nostar@oob{\wg@oob@invfalse\wg@oob} \def\oob{% @@ -91,6 +93,8 @@ % \begin{macrocode} \def\wg@oob#1#2#3#4{ \def\r{0} + \pgfmathparse{#3*(#2-1)}% + \edef\a{\pgfmathresult} \chit@dbg{2}{OOB: `#1'} \foreach[count=\ti from 0] \t/\y in #1{ \xdef\o{\r} @@ -109,20 +113,28 @@ \ifx\m\@empty\def\m{1}\fi \ifx\u\m\def\m{1}\fi \foreach \n in {1,...,\m}{% - \chit@dbg{2}{OOB Chit is `\u'}% + \chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}% \ifx\u\chit@oob@spacer% \chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'} \pgfmathparse{\c+#4}% \xdef\c{\pgfmathresult}% - \else - \ifnum\chitdbglvl>2% - \node[minimum width=#3cm,minimum height=#3cm, - draw,transform shape] at (\c,\r) {}; + \else% + \ifx\u\chit@oob@vspacer% + \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'} + \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)} + \xdef\ll{\pgfmathresult} + \chit@dbg{2}{\string\ll=`\ll'} + \chit@oob@rowupdate(\c,\r){\ll}{#4} + \else + \ifnum\chitdbglvl>2% + \node[minimum width=#3cm,minimum height=#3cm, + draw,transform shape] at (\c,\r) {}; + \fi + \ifx\u\chit@blank\else% + \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);% + \fi% + \chit@oob@cellupdate(\c,\r){#2}{#3}{\y} \fi - \ifx\u\chit@blank\else% - \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);% - \fi% - \chit@oob@cellupdate(\c,\r){#2}{#3}{\y} \fi } \fi @@ -153,7 +165,7 @@ % \chit@dbg{2}{ \space Breaking loop \rr\space > \y}% % \breakforeach% %\else% - \chit@oob@rowupdate(\c,\r){#3}{#4} + \chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing? %\fi } \fi @@ -166,6 +178,169 @@ \@ifnextchar;{\@gobble}{}} % \end{macrocode} % +% Horizontal flow OOB +% +% \begin{macrocode} +\def\wg@star@hoob{\wg@oob@invtrue\wg@hoob} +\def\wg@nostar@hoob{\wg@oob@invfalse\wg@hoob} +\def\hoob{% + \@ifstar{\wg@star@hoob% + }{\wg@nostar@hoob% + }% +} +% \end{macrocode} +% +% The inner macro of \cs{hoob}. The arguments are +% \begin{enumerate} +% \item The list of lists of chits styles +% \item The maximum number of columns +% \item The width of each cell +% \item Additional row spacing between turns +% \end{enumerate} +% +% \begin{macrocode} +\def\wg@hoob#1#2#3#4{ + \def\r{0} + \def\c{0} + \pgfmathparse{#3*(#2-1)}% + \edef\a{\pgfmathresult} + \chit@dbg{2}{OOB: `#1'} + \foreach[count=\ti from 0] \t/\y in #1{ + \xdef\o{\r} + % \def\c{0} + \ifx\t\y\def\y{0}\fi + \chit@dbg{2}{Turn \ti\space(\r,\t,y=\y):'} + \ifx\t\empty\else + % Count how many are left for this turn + \chit@dbg{2}{At start of turn \t\space\string\c=\c} + \def\l{\c}% + \let\ig\empty + \foreach \u/\m in \t{ + \ifx\ig\empty + \ifx\u\empty\else + \ifx\u\m\def\m{1}\fi + \ifx\u\chit@oob@spacer% + \pgfmathparse{\l+\m*#4}\xdef\l{\pgfmathresult} + \chit@dbg{2}{Got \m\space hspace (#4) -> \l} + \else + \ifx\u\chit@oob@vspace% + \xdef\ig{1} + \chit@dbg{2}{Got vspace -> \l (\ig)} + \else + \pgfmathparse{\l+\m*#3} + \xdef\l{\pgfmathresult} + \chit@dbg{2}{Got \m\space units -> \l} + \fi + \fi + \fi + \fi} + % Check if there's enough room + \chit@dbg{2}{To fill the rest of turn needs `\l' compared to + `\a' (#3*(#2-1))} + \pgfmathparse{ifthenelse(abs(\l)>=#3*(#2-1),0,1}% + \xdef\l{\pgfmathresult}% + \chit@dbg{2}{Break or not `\l'} + \ifnum\l=0\chit@oob@turnupdate(\c,\r){#3}{#4}\fi + \fi + \ifwg@oob@inv% + \pic[transform shape] at (\c+.5*#3,\r) {chit/oob turn=\ti};% was dx=0.5 + \else + \pic[transform shape] at (\c+-.5*#3,\r) {chit/oob turn=\ti};% was dx=-0.5 + \fi% + %\chit@oob@cellupdate(\c,\r){#2}{#3}{\y} + \ifx\t\empty\else% + \def\lv{0} + \foreach \u/\m in \t{ + %% \chit@dbg{2}{ `\u'=`\m'} + \ifx\u\empty\else + \ifx\m\@empty\def\m{1}\fi + \ifx\u\m\def\m{1}\fi + \foreach \n in {1,...,\m}{% + \chit@dbg{2}{OOB Chit is `\u' `\chit@oob@spacer'}% + \ifx\u\chit@oob@spacer% + \chit@dbg{3}{Chit `\u' is spacer `\chit@oob@spacer'} + \pgfmathparse{\c+#4}% + \xdef\c{\pgfmathresult}% + \else% + \ifx\u\chit@oob@vspacer% + \chit@dbg{3}{Chit `\u' is vspacer `\chit@oob@vspacer'} + \pgfmathparse{ifthenelse(abs(\c)<0.0001,0,#3)} + \xdef\ll{\pgfmathresult} + \chit@dbg{2}{\string\ll=`\ll'} + \chit@oob@rowupdate(\c,\r){\ll}{#4} + \xdef\lv{1} + \else + \ifnum\chitdbglvl>2% + \node[minimum width=#3cm,minimum height=#3cm, + draw,transform shape] at (\c,\r) {}; + \fi + \ifx\u\chit@blank\else% + \chit[\u=\ti,zone oob point={\u}{\c}{\r}](\c,\r);% + \fi% + \chit@oob@cellupdate(\c,\r){#2}{#3}{\y} + \fi + \fi + } + \fi + } + \fi + \chit@dbg{2}{ End of chits in turn + \ti\space(c=`\c',r=`\r',o='\o',y='\y')} + % --- Not relevant, I think + % IF no units where given, then we force \c to be non-zero so that + % \chit@oob@turnupdate increments the row + % \ifx\t\@empty + % \def\c{#3} + % \chit@dbg{2}{ Turn is empty, set c=`\c'} + % \fi + % --- + %\ifnum\y<0% No explicit number of rows given + % \def\c{#3} + % \chit@dbg{2}{ No explicit number of rows given, set c=`\c'} + %\fi + % In case the user gave and explicit number of rows, add the rows + % that are missing. \y is initially set to the number of + % requested rows, and then decremented every time we go down one + % row. So if the number of rows we did so far is N, and the + % requested number of rows is M, then the loop below adds M-N + % rows. + \ifnum\y>0% + \chit@dbg{2}{ Looping rows from 2 to \y, break when row > \y}% + \foreach \rr in {2,...,\y}{ + %\ifnum\rr>\y% A little funny, but \y can be negative! + % \chit@dbg{2}{ \space Breaking loop \rr\space > \y}% + % \breakforeach% + %\else% + \chit@oob@rowupdate(\c,\r){#3}{0}% Extra spacing? + %\fi + } + \fi + % --- Not relevant I think + % This will zero \c. However, if on entry |\c|>0, then we also + % increment the row + % \chit@oob@turnupdate(\c,\r){#3}{#4} + % --- + % Horizontal spacer + + %\pgfmathparse{ifthenelse(abs(\c)>=\a,1,0)}\xdef\l{\pgfmathresult} + \pgfmathparse{\c+1.5*#4}% + \xdef\c{\pgfmathresult}% + \ifnum\lv=1% + \pgfmathparse{\r-#4} + \chit@oob@rowupdate(\c,\r){0}{#4} + \else + \chit@oob@cellupdate(\c,\r){#2}{#3}{\y} + \ifnum\y<0 + \chit@oob@turnupdate(\c,\r){#3}{#4} + \else + \fi + \fi + % \xdef\y{0} + \chit@dbg{2}{End of turn \ti\space(c=`\c',r=`\r',o='\o',y='\y')} + } + \chit@dbg{3}{End of OOB (c=`\c',r=`\r',y=`\y')} + \@ifnextchar;{\@gobble}{}} +% \end{macrocode} % \iffalse % % -------------------------------------------------------------------- diff --git a/macros/latex/contrib/wargame/source/chit/shape.dtx b/macros/latex/contrib/wargame/source/chit/shape.dtx index 8a3d70fbd0..f68ea25a44 100644 --- a/macros/latex/contrib/wargame/source/chit/shape.dtx +++ b/macros/latex/contrib/wargame/source/chit/shape.dtx @@ -92,7 +92,7 @@ chit/symbol/.style={scale=.4,transform shape}, chit/parts/.style={shape=rectangle,transform shape}, chit/factors/.style={chit/parts,anchor=south}, - chit/left/.style={chit/parts,anchor=south,rotate=90}, + chit/left/.style={chit/parts,anchor=base,rotate=90},%Anchor was south chit/right/.style={chit/parts,anchor=north,rotate=90}, chit/upper left/.style={chit/parts,anchor=north west}, chit/upper right/.style={chit/parts,anchor=north east}, @@ -141,7 +141,8 @@ % \begin{macrocode} \tikzset{% chit/.code={% - \pgfkeys{/tikz/transform shape,/tikz/shape=chit} + \chit@dbg{2}{chit arguments are `#1'}% + \pgfkeys{/tikz/transform shape,/tikz/shape=chit}% \pgfkeys{/chit/.cd,#1}}} % \end{macrocode} % \end{TikzKey} @@ -657,7 +658,11 @@ % % The work horse. This simply makes a \cs{node} with the shape % \texttt{chit}. Note, we allow for a trailing semi-colon -% (\texttt{;}) to have a similar feel to other \TikZ{} macros. +% (\texttt{;}) to have a similar feel to other \TikZ{} macros. +% +% The macro will execute the style \texttt{/tikz/every chit} if +% defined. Note that this will be executed \emph{before} the usual +% \texttt{every chip node} style. % % \begin{macrocode} \def\chit@@@#1#2(#3){% @@ -667,7 +672,7 @@ ^^J Name: `#3'} \let\name\pgfutil@empty% \chit@dbg{1}{=== Before chit node}% - \node[chit={every chit/.try,id=#3,#1}] (tmp) at (#2) {}; + \node[chit={/tikz/every chit/.try,id=#3,#1}] (tmp) at (#2) {}; \chit@dbg{2}{=== After chit node}% \ifx|#3|\relax% \else% diff --git a/macros/latex/contrib/wargame/source/chit/table.dtx b/macros/latex/contrib/wargame/source/chit/table.dtx index 7094e436ed..f99236119e 100644 --- a/macros/latex/contrib/wargame/source/chit/table.dtx +++ b/macros/latex/contrib/wargame/source/chit/table.dtx @@ -7,7 +7,9 @@ % \begin{macrocode} \tikzset{ chit/cell background/.style={fill=black}, + %chit/cell background flipped/.style={fill=black}, blank chit/.style={/chit/frame={draw=none,fill=none}}, + chit/grid lines/.style={dashed}, } % \end{macrocode} % @@ -20,6 +22,10 @@ \def\chit@cellbg(#1,#2)#3{% \draw[chit/cell background](#1-#3/2,#2-#3/2) rectangle++(#3,#3); } +\def\chit@celldblbg(#1,#2)#3{% + \draw[chit/cell background,chit/cell background flipped/.try]% + (#1-#3/2,#2-#3/2) rectangle++(#3,#3); +} % \end{macrocode} % % \begin{Macro}{\ifchits@reset} @@ -83,6 +89,27 @@ \@ifnextchar;{\@gobble}{}} % \end{macrocode} % \end{Macro} +% \begin{Macro}{\chitgrid} +% \begin{enumerate} +% \item columns +% \item rows +% \item cell-size +% \end{enumerate} +% +% \begin{macrocode} +\def\chitgrid#1#2#3{% + \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}% + \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}% + %\draw[red](-#3/2,\rmin)rectangle(#3*#1-#3/2,-\rmax); + \foreach \cc in {0,...,#1}{ + \draw[chit/grid lines] (\cc*#3-#3/2,3*#3/4)--(\cc*#3-#3/2,-\rmax-#3/4);} + %\chit@dbg{0}{Drawing horizontal lines from `\rmin, `-\rmin', ..., `-\rmax'} + \foreach \rr in {\rmin,-\rmin,...,-\rmax}{ + %\chit@dbg{0}{Horizontal line at `\rr'} + \draw[chit/grid lines] (-3*#3/4,\rr)--(#1*#3-#3/4,\rr);} +} +% \end{macrocode} +% \end{Macro} % % \begin{Macro}{\doublechits, % \@doublechits, @@ -154,7 +181,7 @@ \chit@cellbg(\c,\r){#3} \chit[\u=\ti](\c,\r) \chit@dbl@flip(\c,\r){#3} - \chit@cellbg(\mc,\r){#3} + \chit@celldblbg(\mc,\r){#3} \chit[\u\space flipped=\ti,zone turn=\t,zone mult=\n](\mc,\r) \chit@dbl@cellupdate(\c,\r){#2}{#3} \fi @@ -166,10 +193,39 @@ \draw[dashed](0,-3*#3/4)--(0,\r-#3/4);% \draw[dashed,<-] (#3/5,-2*#3/3)--(#3/2,-2*#3/3) node[transform shape,anchor=west]{Back};% \draw[dashed,<-] (-#3/5,-2*#3/3)--(-#3/2,-2*#3/3) node[transform shape,anchor=east]{Front};% + % \foreach \cc in {0,...,#2}{ + % \draw[dashed] (\cc*#3,-3*#3/4)--(\cc*#3,\r-#3/4); + % \draw[dashed] (-\cc*#3,-3*#3/4)--(-\cc*#3,\r-#3/4);} + % \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}% + % \chit@dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\r'} + % \foreach \rr in {-\rmin,\rmin,...,\r}{ + % \chit@dbg{0}{Horizontal line at `\rr'} + % \draw[dashed] (-#2*#3-#3/4,\rr)--(#2*#3+#3/4,\rr);} \@ifnextchar;{\@gobble}{}} % \end{macrocode} % \end{Macro} % +% \begin{Macro}{\doublechitgrid} +% \begin{enumerate} +% \item columns +% \item rows +% \item cell-size +% \end{enumerate} +% +% \begin{macrocode} +\def\doublechitgrid#1#2#3{% + \pgfmathparse{#3/2}\edef\rmin{\pgfmathresult}% + \pgfmathparse{#2*#3-#3/2}\edef\rmax{\pgfmathresult}% + \foreach \cc in {0,...,#1}{ + \draw[chit/grid lines] (\cc*#3,-3*#3/4)--(\cc*#3,\rmax+#3/4); + \draw[chit/grid lines] (-\cc*#3,-3*#3/4)--(-\cc*#3,\rmax+#3/4);} + %\chit@dbg{0}{Drawing horizontal lines from `-\rmin, `\rmin', ..., `\rmax'} + \foreach \rr in {-\rmin,\rmin,...,\rmax}{ + %\chit@dbg{0}{Horizontal line at `\rr'} + \draw[chit/grid lines] (-#1*#3-#3/4,\rr)--(#1*#3+#3/4,\rr);} +} +% \end{macrocode} +% \end{Macro} % \iffalse % % -------------------------------------------------------------------- diff --git a/macros/latex/contrib/wargame/source/hex/labels.dtx b/macros/latex/contrib/wargame/source/hex/labels.dtx index 7767dcc661..f622bf6cda 100644 --- a/macros/latex/contrib/wargame/source/hex/labels.dtx +++ b/macros/latex/contrib/wargame/source/hex/labels.dtx @@ -132,7 +132,7 @@ % % \begin{macrocode} \def\hex@do@label{% - \hex@dbg{1}{Hex label: `\meaning\hex@label'}% + \hex@dbg{3}{Hex label: `\meaning\hex@label'}% \edef\hex@l@tmp{[% /hex/label/.cd,% rotate=0,% diff --git a/macros/latex/contrib/wargame/source/hex/ridges.dtx b/macros/latex/contrib/wargame/source/hex/ridges.dtx index 24552e36e2..658f55888b 100644 --- a/macros/latex/contrib/wargame/source/hex/ridges.dtx +++ b/macros/latex/contrib/wargame/source/hex/ridges.dtx @@ -157,11 +157,12 @@ \xdef\hex@r@p{\hex@r@p ($(300:\hex@r@r)+(-120:\hex@r@t/2)$)} \fi \ifhex@r@ne - \xdef\hex@r@p{\hex@r@p --cycle} + %\xdef\hex@r@p{\hex@r@p --cycle} + \xdef\hex@r@p{\hex@r@p -- (0:\hex@r@r)} \else \xdef\hex@r@p{\hex@r@p --(.5:\hex@r@r)} \fi - \hex@dbg{4}{Ridge along se: `\hex@r@p'} + \hex@dbg{4}{Ridge along south east: `\hex@r@p'} \fi \hex@dbg{3}{ Ridges path: \hex@r@p} % \draw[red] \hex@r@p; diff --git a/macros/latex/contrib/wargame/source/hex/terrain.dtx b/macros/latex/contrib/wargame/source/hex/terrain.dtx index 4c486adf77..9d15a555ec 100644 --- a/macros/latex/contrib/wargame/source/hex/terrain.dtx +++ b/macros/latex/contrib/wargame/source/hex/terrain.dtx @@ -37,6 +37,7 @@ % select the common terrains. % % \begin{macrocode} +\newif\if@hex@t@rot\@hex@t@rotfalse% \tikzset{% /hex/terrain/.search also={/tikz},% /hex/terrain/.cd,% @@ -44,6 +45,7 @@ image/.store in=\hex@t@image,% code/.store in=\hex@t@code,% clip/.store in=\hex@t@clip,% + random rotation/.is if=@hex@t@rot, pic/.default=, image/.default=, code/.default=, @@ -137,8 +139,23 @@ \@ifundefined{hex@t@code}{\let\hex@t@code\empty}{} % \end{macrocode} % +% Possible make rotation. We define a scope and rotate within that. +% +% \begin{macrocode} + \def\hex@t@angle{0}% + \if@hex@t@rot% + \pgfmathrandominteger{\hex@t@angle}{0}{5} + \pgfmathparse{int(60*\hex@t@angle)}\edef\hex@t@angle{\pgfmathresult}% + \fi% + \hex@dbg{5}{Will rotate terrain by `\hex@t@angle'}% +% \end{macrocode} +% +% If we have specified code for the terrain, then execute that. +% % \begin{macrocode} - \ifx\hex@t@code\empty\else\hex@t@code\fi% + \scope[rotate=\hex@t@angle]% + \ifx\hex@t@code\empty\else\hex@t@code\fi% + \endscope% End rotate code % \end{macrocode} % First we check if we have not got terrain images, but terrain % pictures. If we have that, we process these in turn. Note, the @@ -154,7 +171,9 @@ \hex@dbg{5}{Terrain pictures}% \pgfpointorigin\wg@tmpa=\pgf@x\wg@tmpb=\pgf@y% \foreach \i in \hex@t@pic{% - \wg@pic@all{\i}{}{\the\wg@tmpa,\the\wg@tmpb}{}}% + \wg@pic@all{\i}{}{\the\wg@tmpa,\the\wg@tmpb}{% + rotate=\hex@t@angle, + transform shape}}% \fi% We have pictures. % \end{macrocode} % @@ -172,6 +191,7 @@ \expandafter\wg@node{% \includegraphics[width=2cm]{\i}}\@endwg@node % {}{\wg@tmpa,\wg@tmpb}{% + rotate=\hex@t@angle,% shape=rectangle,% anchor=center,% transform shape,% diff --git a/macros/latex/contrib/wargame/source/tests/chits.dtx b/macros/latex/contrib/wargame/source/tests/chits.dtx index 7dcf26c50d..966e3b4a9f 100644 --- a/macros/latex/contrib/wargame/source/tests/chits.dtx +++ b/macros/latex/contrib/wargame/source/tests/chits.dtx @@ -6,7 +6,11 @@ % Some chits for testing stuff % % \begin{macrocode} -\def\firstchit{ +\makeatletter +\def\firstchit{% + \@ifnextchar[{\@firstchit}{\@firstchit[]}%] +}% +\def\@firstchit[#1]{ % \chitdbglvl=5 % \natoappdbglvl=5 \chit[symbol={ @@ -17,13 +21,14 @@ left={text=A}, frame={fill=yellow!50!black}, ultra thick, - command=land}, + command=land, + }, left={chit/identifier={1}}, right={chit/identifier={2}}, factors={chit/2 factors={4,8}}, frame={draw=black}, - color=white,text=yellow,fill={blue}]} -\makeatletter + color=white,text=yellow,fill={blue}, + #1]} \def\secondchit{% \@ifnextchar({\second@chit}{\second@chit(0,0)}%) } @@ -34,6 +39,7 @@ command=air](0,-.15)}, left={[{red,font=\noexpand\sffamily}]chit/identifier={Fighter}}, right={chit/identifier={USAF}}, + fill=white, factors={chit/1 factor=3}}] at (#1){};} \def\thirdchit{ \chit[symbol={[echelon=battalion, diff --git a/macros/latex/contrib/wargame/source/tests/test.tex b/macros/latex/contrib/wargame/source/tests/test.tex index 5833d679f2..49062b70f0 100644 --- a/macros/latex/contrib/wargame/source/tests/test.tex +++ b/macros/latex/contrib/wargame/source/tests/test.tex @@ -2,6 +2,7 @@ \usepackage{wargame} \usetikzlibrary{decorations.markings} +\usetikzlibrary{shadows.blur} \title{A test of \textsf{wargame}} \author{} \date{} @@ -28,7 +29,7 @@ \section{Some chits} -\begin{tikzpicture} +\begin{tikzpicture}[every chit node/.style={blur shadow={shadow blur steps=5}}] \fill[red!50] (1,-1) rectangle (3,1); \firstchit(0,0)% %\secondchit(2,0)% @@ -45,18 +46,20 @@ \end{tikzpicture} \section{Chits on a board} -\begin{tikzpicture} +\begin{tikzpicture}[every chit/.style={chit drop}] + \chitdbglvl=5 \begin{scope}[every hex/.style={/hex/label=auto},transform shape] \boardframe[0.5](c=0,r=0)(c=3,r=3) \boardclip(c=0,r=0)(c=3,r=3){fill=white} \testmap{} - \firstchit(hex cs:c=2,r=1) - \secondchit(hex cs:c=3,r=0) + \firstchit[no chit drop](hex cs:c=2,r=2) + %\secondchit(hex cs:c=3,r=0) \thirdchit(hex cs:c=0,r=3) \stackchits(hex cs:c=0,r=1)(.3,.3){ \noexpand\firstchit, - \noexpand\secondchit/\noexpand\chit[{full=chit/eliminate}]} + \noexpand\secondchit%/\noexpand\eliminatechit + } \begin{scope}[m/.style={hex/long move=green}] \path[m] (hex cs:c=3,r=0) -- (hex cs:c=3,r=1)--(hex cs:c=3,r=2); diff --git a/macros/latex/contrib/wargame/source/util/export.dtx b/macros/latex/contrib/wargame/source/util/export.dtx index fde067dfe8..09f74c0513 100644 --- a/macros/latex/contrib/wargame/source/util/export.dtx +++ b/macros/latex/contrib/wargame/source/util/export.dtx @@ -72,6 +72,7 @@ % % Preceed all images (\textsf{tikzpicture}) with this command % +% % First argument is the name of the image. This can be anything. % Note that for counters, if the name ends in \texttt{flipped} then it % is considered the backside of a counter. @@ -140,13 +141,32 @@ % % Make separate images for each counter (single sided). % +% First optional argument is the group to put the chits into. +% Second optional argument is options to give to each Tikz picture +% environment. Third, mandatory, argument is the list of chit +% identifiers to render. +% % \begin{macrocode} -\newcommand\chitimages[2][]{% +\def\wg@add@drop@margin{% + \@ifundefined{wg@drop@margin}{}{ + \dimen0=\wg@drop@margin + % \ifwg@chit@drop + \ifdim\dimen0>0pt% + \path ($(current bounding box.north east)+(45:\wg@drop@margin)$) + -- ($(current bounding box.south west)+(225:\wg@drop@margin)$); + \fi}} +\def\chitimages{% + \@ifnextchar[{\@chitimages}{\chitimages[]}%] +}% +\def\@chitimages[#1]{% + \@ifnextchar[{\@@chitimages[#1]}{\@@chitimages[#1][]}%] +}% +\def\@@chitimages[#1][#2]#3{% \begingroup% \let\chit@report\do@chit@report% \let\natoapp@report\do@natoapp@report% - \chit@dbg{2}{chits to make images of `#2'}% - \foreach[count=\ti from 0] \t/\x in #2{% + \chit@dbg{2}{chits to make images of `#3'}% + \foreach[count=\ti from 0] \t/\x in #3{% \chit@dbg{2}{^^JRow: `\t' (`\x')} \ifx\t\empty\else% Ignore empty rows \chit@dbg{5}{^^JSubcategory: `\x' (default `#1')} @@ -156,14 +176,17 @@ \ifx\u\empty\else% Ignore empty cells \ifx\u\chit@blank\else% \chit@dbg{2}{Next chit `\u' with possible multiplicity `\m'}% - \ifx\m\@empty\def\m{1}\fi% If not multiplicity defined + \ifx\m\@empty\def\m{1}\fi% If no multiplicity defined \ifx\u\m\def\m{1}\fi% If the same as unit \chit@dbg{2}{Next chit `\u' multiplicity `\m'}% %% We only make one copy of the chit, since we can duplicate %% it in VASSAL \info*{\u}{counter}{\x} - \begin{tikzpicture} + \nopagecolor% + \gdef\wg@drop@margin{0pt}% + \begin{tikzpicture}[chit has drop=false,#2] \chit[\u=\ti]% + \wg@add@drop@margin% \end{tikzpicture} \end@info% %% \foreach \n in {1,...,\m}{% Make a number of copies @@ -189,14 +212,25 @@ % % Make separate images for each counter (double sided). The back-side % counters must be defined by append `\texttt{ flipped}' the front -% face name +% face name. +% +% First optional argument is the group to put the chits into. +% Second optional argument is options to give to each Tikz picture +% environment. Third, mandatory, argument is the list of chit +% identifiers to render. % % \begin{macrocode} -\newcommand\doublechitimages[2][]{% +\def\doublechitimages{% + \@ifnextchar[{\@doublechitimages}{\doublechitimages[]}%] +}% +\def\@doublechitimages[#1]{% + \@ifnextchar[{\@@doublechitimages[#1]}{\@@doublechitimages[#1][]}%] +}% +\def\@@doublechitimages[#1][#2]#3{% \begingroup% \let\chit@report\do@chit@report% \let\natoapp@report\do@natoapp@report% - \foreach[count=\ti from 0] \t/\x in #2{% + \foreach[count=\ti from 0] \t/\x in #3{% \ifx\t\empty\else% Ignore empty rows \chit@dbg{5}{^^JSubcategory: `\x' (default `#1')} % Take sub-category or default @@ -213,13 +247,18 @@ %% We only make one copy of the chit, since we can duplicate %% it in VASSAL \info*{\u}{counter}{\x}% - \begin{tikzpicture}% + \nopagecolor% + \gdef\wg@drop@margin{0pt}% + \begin{tikzpicture}[chit has drop=false,#2]% \chit[\u=\ti]% + \wg@add@drop@margin% \end{tikzpicture}% \end@info% \info*{\s}{counter}{\x}% - \begin{tikzpicture}% + \nopagecolor% + \begin{tikzpicture}[chit has drop=false,#2]% \chit[\s=\ti]% + \wg@add@drop@margin% \end{tikzpicture}% \end@info% %% \foreach \n in {1,...,\m}{% Make a number of copies @@ -414,7 +453,7 @@ \def\hex@col{0}% \def\hex@row{0}% \node[hex,inner sep=0,outer sep=0]{% - \message{^^JHex label: `\meaning\hex@label'}% + %\message{^^JHex label: `\meaning\hex@label'}% \global\let\mk@label\hex@label}}}% % \end{macrocode} % @@ -427,7 +466,7 @@ \edef\mk@i{\mk@i\space} %% Everything is made into centimeters \mk@w{ \mk@i "units": "cm",} - \hex@dbg{0}{Label: `\meaning\mk@label'} + \hex@dbg{3}{Label: `\meaning\mk@label'} \@ifundefined{mk@label}{}{\mk@w{ \mk@i "labels": "\mk@label",}} %% Write out coordinate options as "coords" object \mk@w{ \mk@i"coords": \@lbchar}% @@ -577,7 +616,7 @@ % optional is the group to add the markers to. % % \begin{macrocode} -\def\wg@gennumberm@rkers#1#2#3{ +\def\wg@gennumberm@rkers#1#2#3#4{ \message{^^JNumbered markers: Type=`#1' Max=`#2' Category=`#3'} \def\markers{} \def\keys{} @@ -585,24 +624,37 @@ \xdef\keys{/tikz/#1 \i/.style={/tikz/#1=\i},\keys} \xdef\markers{\markers,#1 \i}} {% - \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}% + \nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3][#4]{\markers}}}% \tikzset{ wg hidden unit/.pic={}, wg hidden unit/.style={ chit={ + no chit drop, frame={draw=none,fill=none}, full=wg hidden unit}}} -\DeclareRobustCommand\battlemarkers[2][BattleMarkers]{% - \wg@gennumberm@rkers{battle marker}{#2}{#1}% +% +% First optional argument are extra styles +% Second is category +% Third is number of markers +% +\def\battlemarkers{% + \@ifnextchar[{\@battlemarkers}{\battlemarkers[]}%] +}% +\def\@battlemarkers[#1]{% + \@ifnextchar[{\@@battlemarkers[#1]}{\battlemarkers[#1][BattleMarkers]}%] +}% +\def\@@battlemarkers[#1][#2]#3{% + \wg@gennumberm@rkers{battle marker}{#3}{#2}{#1}% \message{^^JMake a hidden unit and add to Markers category} {% \nopagecolor% \chitimages[Markers]{{wg hidden unit}}% % \info{battle-marker-icon}{icon}{}% - \tikz[scale=.7,transform shape]{\pic{battle marker=0};}% + \tikz[scale=.7,transform shape,auto icon more/.try]{% + \pic{battle marker=0};}% \info{clear-battles-icon}{icon}{} - \tikz[scale=.4,transform shape]{% + \tikz[scale=.4,transform shape,auto icon more/.try]{% \pic{eliminate icon}; \pic[scale=.7,transform shape] at (-.3,0) {battle marker=0};}% }% @@ -613,21 +665,40 @@ % Optional is the group to add the markers to. % % \begin{macrocode} -\def\wg@gencolorm@rkers#1#2#3{% +\def\wg@gencolorm@rkers#1#2#3#4{% \def\markers{} \def\keys{} - \foreach \o/\f in {#2}{% + \foreach \o/\f/\n [count=\i] in {#2}{% + \ifx\n\f\def\n{\o}\fi% \ifx\o\f\def\f{white}\fi% - \message{^^JOdds marker `#1 \o' w/fill `\f'}% - \xdef\keys{/tikz/#1 \o/.style={/tikz/#1={\o,\f}},\keys} - \xdef\markers{\markers,#1 \o}} - {\nopagecolor\pgfkeysalsofrom{\keys}\chitimages[#3]{\markers}}}% -\DeclareRobustCommand\oddsmarkers[2][OddsMarkers]{% - \wg@gencolorm@rkers{odds marker}{#2}{#1}% + \message{^^JColour no \i marker `#1 \n' w/fill `\f' text `\o'}% + \protected@xdef\keys{/tikz/#1 \n/.style={/tikz/#1={\o,\f}},\keys} + \xdef\markers{\markers,#1 \n} + }% + {% + \nopagecolor% + \pgfkeysalsofrom{\keys}% + \chitimages[#3][#4]{\markers}% + }% +}% +% +% First optional argument are extra styles +% Second is category +% Third is marker list +% +\def\oddsmarkers{% + \@ifnextchar[{\@oddsmarkers}{\oddsmarkers[]}%] +}% +\def\@oddsmarkers[#1]{% + \@ifnextchar[{\@@oddsmarkers[#1]}{\oddsmarkers[#1][OddsMarkers]}%] +}% +\def\@@oddsmarkers[#1][#2]#3{% + \wg@gencolorm@rkers{odds marker}{#3}{#2}{#1}% \info{odds-battles-icon}{icon}{} - \tikz[scale=.5,transform shape]{\pic{odds marker={?:?,white}}} + \tikz[scale=.5,transform shape,auto icon more/.try]{% + \pic{odds marker={?:?,white}}} \info{resolve-battles-icon}{icon}{} - \tikz[scale=.3,transform shape]{% + \tikz[scale=.3,transform shape,auto icon more/.try]{% \pic{dice}; \pic[scale=1.2,transform shape] at (-.2,-.2) {battle marker=0};}% } @@ -636,40 +707,51 @@ % Make results markers. Mandatory argument is a list of results and % fill colours. Optional is the group to add the markers to. % +% +% First optional argument are extra styles +% Second is category +% Third is marker list +% % \begin{macrocode} -\DeclareRobustCommand\resultmarkers[2][ResultMarkers]{% - \wg@gencolorm@rkers{result marker}{#2}{#1}} +\def\resultmarkers{% + \@ifnextchar[{\@resultmarkers}{\resultmarkers[]}%] +}% +\def\@resultmarkers[#1]{% + \@ifnextchar[{\@@resultmarkers[#1]}{\resultmarkers[#1][ResultMarkers]}%] +}% +\def\@@resultmarkers[#1][#2]#3{% + \wg@gencolorm@rkers{result marker}{#3}{#2}{#1}}% % \end{macrocode} % % Common icons used by many modules % % \begin{macrocode} -\DeclareRobustCommand\commonicons[2]{% +\DeclareRobustCommand\commonicons[3][]{% \begingroup% \nopagecolor% - \tikzset{icon/.style={scale=.4,transform shape}}% + \tikzset{auto icon/.style={scale=.4,transform shape,#1}}% % \info{pool-icon}{icon}{} - \tikz[icon]{\pic{pool icon};} + \tikz[auto icon,auto icon more/.try]{\pic{pool icon};} % \info{oob-icon}{icon}{}% - \tikz[icon]{\pic{oob icon={#1}{#2}};}% + \tikz[auto icon,auto icon more/.try]{\pic{oob icon={#2}{#3}};}% % \info{flip-icon}{icon}{}% - \tikz[icon]{\pic{flip icon};}% + \tikz[auto icon,auto icon more/.try]{\pic{flip icon};}% % \info{eliminate-icon}{icon}{}% - \tikz[icon]{\pic{eliminate icon};}% + \tikz[auto icon,auto icon more/.try]{\pic{eliminate icon};}% % \info{restore-icon}{icon}{}% - \tikz[icon]{\pic{restore icon};}% + \tikz[auto icon,auto icon more/.try]{\pic{restore icon};}% % \info{dice-icon}{icon}{}% - \tikz[icon,scale=.9]{\pic{dice};}% + \tikz[auto icon,scale=.9,auto icon more/.try]{\pic{dice};}% % \info{unit-icon}{icon}{}% - \tikz[icon,scale=.7]{% - \chit[fill=#1, + \tikz[auto icon,scale=.7,auto icon more/.try]{% + \chit[fill=#2, symbol={[ scale line widths, line width=1pt, @@ -677,7 +759,29 @@ command=land, main=infantry, scale=1.3](0,-.15)}]}% - \endgroup% + % + \info{layer-icon}{icon}{}% + \begin{tikzpicture}[scale=.25] + \foreach \i in {-1,0,1}{ + \scoped[shift={(0,\i*.15)}]{ + \draw[black,fill=white] (-.5,0) + --(0,.3)--(.5,0)--(0,-.3)--cycle; + } + } + \end{tikzpicture}% + % + \info{los-icon}{icon}{} + \begin{tikzpicture}[scale=.25] + \draw[scale line widths,line width=2pt,fill=white](-.5,0) + to[out=70,in=110] (.5,0) + to[out=-110,in=-70] cycle; + \begin{scope}[even odd rule] + \clip circle(.2); + \fill circle(.2) (125:.18) circle(.1); + \end{scope} + \end{tikzpicture}% + % + \endgroup% } % \end{macrocode} % @@ -708,9 +812,11 @@ \foreach \v/\p in {#5}{% \info{#3-\v}{die-roll}{#3} \tikz[#1]{ - \node[shape=#4,transform shape,draw=none,fill=black,opacity=.5] - at (.05,-.03){}; - \node[shape=#4,#2,transform shape]{\p};}}} + %\node[shape=#4,transform shape,draw=none,fill=black,opacity=.5] + %at (.05,-.03){}; + \node[shape=#4,#2,transform shape, + chit drop + ]{\p};\wg@add@drop@margin{}}}} % \end{macrocode} % % \subsubsection{Hooks into chits, etc.} @@ -809,6 +915,28 @@ \mk@w{ \mk@i\space "end": 0} \mk@w{ \mk@i \@rbchar} } +\tikzset{ + chit drop margin/.store in=\wg@drop@margin, + chit drop shadows/.code={ + \pgfkeysalso{% + /tikz/every chit node/.prefix style={chit drop={#1}}, + /tikz/chit has drop=true} + }, + chit drop shadows/.default=, + marker drop shadows/.code={ + \pgfkeysalso{% + /tikz/every battle marker/.prefix style={chit drop={#1}}, + /tikz/every odds marker/.prefix style={chit drop={#1}}, + /tikz/every result marker/.prefix style={chit drop={#1}}, + /tikz/auto icon more/.prefix style={no chit drop}}}, + marker drop shadows/.default={ + chit has drop=false, + shadow xshift=0.04cm, + shadow yshift=-0.04cm, + shadow blur radius=0.04cm} +} + + % \end{macrocode} % % diff --git a/macros/latex/contrib/wargame/source/util/tikz.dtx b/macros/latex/contrib/wargame/source/util/tikz.dtx index fa31a7b58c..2f6dbefc17 100644 --- a/macros/latex/contrib/wargame/source/util/tikz.dtx +++ b/macros/latex/contrib/wargame/source/util/tikz.dtx @@ -86,12 +86,17 @@ % Save pgf rounded corners macro % \let\wg@pgfsetcornersarced\pgfsetcornersarced \def\wg@setcornersarched#1{% - \ifx|#1|\else% - \edef\pgf@corner@arc{{#1}{#1}}% - \pgf@arccornerstrue% - \ifdim#1=0pt% - \pgf@arccornersfalse% - \fi\fi} + \def\arg{#1}% + \let\isarched\relax% Cannot set \ifpgf@arccorners directly inside + % other \if + \ifx\arg\@empty\else% + \edef\pgf@corner@arc{{#1}{#1}}% + \let\isarched\pgf@arccornerstrue% + \ifdim#1=0pt% + \let\isarched\pgf@arccornersfalse% + \fi% + \fi% + \isarched} \newdimen\wg@lw@scaled\wg@lw@scaled=1pt \def\wg@getscale{% \pgfgettransformentries{% diff --git a/macros/latex/contrib/wargame/source/utils/wgexport.py b/macros/latex/contrib/wargame/source/utils/wgexport.py index a09a7e4257..d573b63d36 100755 --- a/macros/latex/contrib/wargame/source/utils/wgexport.py +++ b/macros/latex/contrib/wargame/source/utils/wgexport.py @@ -208,6 +208,8 @@ CTRL_SHIFT = CTRL+SHIFT ALT_SHIFT = ALT+SHIFT NONE = '\ue004' NONE_MOD = 0 + +# -------------------------------------------------------------------- def key(let,mod=CTRL): '''Encode a key sequence @@ -220,6 +222,8 @@ def key(let,mod=CTRL): Modifier mask ''' return f'{ord(let)},{mod}' + +# -------------------------------------------------------------------- # def hexcolor(s): if isinstance(s,str): @@ -241,6 +245,7 @@ def hexcolor(s): return rgb(int(r*256),int(g*256),int(b*256)) +# -------------------------------------------------------------------- # Colour encoding def rgb(r,g,b): '''Encode RGB colour @@ -261,6 +266,7 @@ def rgb(r,g,b): ''' return ','.join([str(r),str(g),str(b)]) +# -------------------------------------------------------------------- def rgba(r,g,b,a): '''Encode RGBA colour @@ -282,6 +288,7 @@ def rgba(r,g,b,a): ''' return ','.join([str(r),str(g),str(b),str(a)]) +# -------------------------------------------------------------------- def dumpTree(node,ind=''): '''Dump the tree of nodes @@ -296,6 +303,12 @@ def dumpTree(node,ind=''): for c in node.childNodes: dumpTree(c,ind+' ') +# -------------------------------------------------------------------- +def registerElement(cls): + + Element.known_tags[cls.TAG] = cls + + # # EOF # @@ -310,6 +323,8 @@ class Element: MAP = MODULE + 'map.' PICKER = MAP + 'boardPicker.' BOARD = PICKER + 'board.' + known_tags = {} + def __init__(self,parent,tag,node=None,**kwargs): '''Create a new element @@ -429,9 +444,14 @@ class Element: return {c[key] : c for c in cand} return cand - def getParent(self,cls,checkTag=True): + def getParent(self,cls=None,checkTag=True): if self._node.parentNode is None: return None + if cls is None: + cls = self.getTagClass(self._node.parentNode.tagName) + checkTag = False + if cls is None: + return None if checkTag and self._node.parentNode.tagName != cls.TAG: return None return cls(self,node=self._node.parentNode) @@ -440,6 +460,10 @@ class Element: '''Searches back until we find the parent with the right class, or none ''' + try: + iter(cls) + except: + cls = [cls] t = {c.TAG: c for c in cls} p = self._node.parentNode while p is not None: @@ -447,6 +471,11 @@ class Element: if c is not None: return c(self,node=p) p = p.parentNode return None + + def getTagClass(self,tag): + '''Get class corresponding to the tag''' + if tag not in self.known_tags: return None; + return self.known_tags[tag] # ---------------------------------------------------------------- # Adders @@ -518,7 +547,83 @@ class DummyElement(Element): ''' super(DummyElement,self).__init__(parent,'Dummy',node=node) +# -------------------------------------------------------------------- +class ToolbarElement(Element): + def __init__(self, + parent, + tag, + node = None, + name = '', # Toolbar element name + tooltip = '', # Tool tip + text = '', # Button text + icon = '', # Button icon, + hotkey = '', # Named key or key stroke + canDisable = False, + propertyGate = '', + disabledIcon = '', + **kwargs): + '''Base class for toolbar elements. + Parameters + ---------- + parent : Element + Parent element if any + tag : str + Element tag + node : XMLNode + Possible node - when reading back + name : str + Name of element (user reminder). If not set, and tooltip is set, + set to tooltip + toolttip : str + Tool tip when hovering. If not set, and name is set, then + use name as tooltip. + text : str + Text of button + icon : str + Image path for button image + hotkey : str + Named key or key-sequence + canDisable : bool + If true, then the element can be disabled + propertyGate : str + Name of a global property. When this property is `true`, + then this element is _disabled_. Note that this _must_ be + the name of a property - it cannot be a BeanShell + expression. + disabledIcon : str + Path to image to use when the element is disabled. + kwargs : dict + Other attributes to set on the element + ''' + if name == '' and tooltip != '': name = tooltip + if name != '' and tooltip == '': tooltip = name + + # Build arguments for super class + args = { + 'node': node, + 'name': name, + 'icon': icon, + 'tooltip': tooltip, + 'hotkey': hotkey, + 'canDisable': canDisable, + 'propertyGate': propertyGate, + 'disabledIcon': disabledIcon } + bt = kwargs.pop('buttonText',None) + # If the element expects buttonText attribute, then do not set + # the text attribute - some elements interpret that as a + # legacy name attribute, + if bt is not None: + args['buttonText'] = bt + else: + args['text'] = text + args.update(kwargs) + + super(ToolbarElement,self).__init__(parent, + tag, + **args) + # print('Attributes\n','\n'.join([f'- {k}="{v}"' for k,v in self._node.attributes.items()])) + # # EOF # @@ -526,26 +631,28 @@ class DummyElement(Element): # From globalkey.py # -------------------------------------------------------------------- -class GlobalKey(Element): +class GlobalKey(ToolbarElement): SELECTED = 'MAP|false|MAP|||||0|0||true|Selected|true|EQUALS' def __init__(self, parent, tag, node = None, name = '', + icon = '', + tooltip = '', buttonHotkey = '', - hotkey = '', buttonText = '', canDisable = False, + propertyGate = '', + disabledIcon = '', + # Local + hotkey = '', deckCount = '-1', filter = '', - propertyGate = '', reportFormat = '', reportSingle = False, singleMap = True, - target = SELECTED, - tooltip = '', - icon = ''): + target = SELECTED): ''' Parameters ---------- @@ -569,28 +676,26 @@ class GlobalKey(Element): Default targets are selected units ''' - nme = (name if len(name) > 0 else - tooltip if len(tooltip) > 0 else '') - tip = (tooltip if len(tooltip) > 0 else - name if len(name) > 0 else '') + super(GlobalKey,self).\ __init__(parent, tag, node = node, - name = nme, + name = name, + icon = icon, + tooltip = tooltip, buttonHotkey = buttonHotkey, # This hot key - hotkey = hotkey, # Target hot key buttonText = buttonText, canDisable = canDisable, + propertyGate = propertyGate, + disabledIcon = disabledIcon, + hotkey = hotkey, # Target hot key deckCount = deckCount, filter = filter, - propertyGate = propertyGate, reportFormat = reportFormat, reportSingle = reportSingle, singleMap = singleMap, - target = target, - tooltip = tip, - icon = icon) + target = target) # # EOF # @@ -600,7 +705,7 @@ class GlobalKey(Element): # -------------------------------------------------------------------- class GameElementService: def getGame(self): - return self.getParent(Game) + return self.getParentOfClass(Game) # -------------------------------------------------------------------- class GameElement(Element,GameElementService): @@ -608,23 +713,34 @@ class GameElement(Element,GameElementService): super(GameElement,self).__init__(game,tag,node=node,**kwargs) # -------------------------------------------------------------------- -class Notes(GameElement): +class Notes(ToolbarElement,GameElementService): TAG = Element.MODULE+'NotesWindow' def __init__(self,elem,node=None, - name = 'Notes', - buttonText = '', - hotkey = key('N',ALT), - icon = '/images/notes.gif', - tooltip = 'Show notes window'): - super(Notes,self).__init__(elem,self.TAG,node=node, - name = name, - buttonText = buttonText, - hotkey = hotkey, - icon = icon, - tooltip = tooltip) + name = 'Notes', # Toolbar element name + tooltip = 'Show notes window', # Tool tip + text = '', # Button text + icon = '/images/notes.gif', # Button icon, + hotkey = key('N',ALT), # Named key or key stroke + canDisable = False, + propertyGate = '', + disabledIcon = '', + description = ''): + super(Notes,self).__init__(elem,self.TAG, + node = node, + name = name, + tooltip = tooltip, + text = text, + icon = icon, + hotkey = hotkey, + canDisable = canDisable, + propertyGate = propertyGate, + disabledIcon = disabledIcon, + description = description) def encode(self): return ['NOTES\t\\','PNOTES'] +registerElement(Notes) + # -------------------------------------------------------------------- class PredefinedSetup(GameElement): TAG = Element.MODULE+'PredefinedSetup' @@ -673,6 +789,7 @@ class PredefinedSetup(GameElement): +registerElement(PredefinedSetup) # -------------------------------------------------------------------- class GlobalTranslatableMessages(GameElement): @@ -690,11 +807,15 @@ class GlobalTranslatableMessages(GameElement): super(GlobalTranslatableMessages,self).\ __init__(elem,self.TAG,node=node) +registerElement(GlobalTranslatableMessages) + # -------------------------------------------------------------------- class Language(GameElement): TAG = 'VASSAL.i18n.Language' def __init__(self,elem,node=None,**kwargs): super(Languate,self).__init__(sele,self.TAG,node=none,**kwargs) + +registerElement(Language) # -------------------------------------------------------------------- class Chatter(GameElement): @@ -712,6 +833,8 @@ class Chatter(GameElement): Attributes ''' super(Chatter,self).__init__(elem,self.TAG,node=node,**kwargs) + +registerElement(Chatter) # -------------------------------------------------------------------- class KeyNamer(GameElement): @@ -730,6 +853,8 @@ class KeyNamer(GameElement): ''' super(KeyNamer,self).__init__(elem,self.TAG,node=node,**kwargs) +registerElement(KeyNamer) + # -------------------------------------------------------------------- # 0: description = tooltip if len(tooltip) <= 0 and len(description) > 0: @@ -1310,6 +1456,7 @@ class Menu(GameElement): __init__(game, self.TAG, node = node, + name = name, canDisable = canDisable, description = description, disabledIcon = disabledIcon, @@ -1320,6 +1467,8 @@ class Menu(GameElement): text = text, tooltip = tooltip) +registerElement(Menu) + # -------------------------------------------------------------------- class SymbolicDice(GameElement): @@ -1370,6 +1519,8 @@ class SymbolicDice(GameElement): def getSymbolicDice(self): return self.getParent(SymbolicDice) +registerElement(SymbolicDice) + # -------------------------------------------------------------------- class SpecialDie(GameElement): @@ -1399,8 +1550,7 @@ class SpecialDie(GameElement): def getSymbolicDice(self): return self.getParent(SymbolicDice) - - +registerElement(SpecialDie) # -------------------------------------------------------------------- class DieFace(GameElement): @@ -1421,6 +1571,9 @@ class DieFace(GameElement): def getSpecialDie(self): return self.getParent(SpecialDie) + +registerElement(DieFace) + # # EOF # @@ -1450,6 +1603,223 @@ class MapElement(Element,MapElementService): super(MapElement,self).__init__(map,tag,node=node,**kwargs) +# -------------------------------------------------------------------- +class PieceLayers(MapElement): + TAG=Element.MAP+'LayeredPieceCollection' + def __init__(self,map,node=None, + property = 'PieceLayer', + description = '', + layerOrder = []): + super(PieceLayers,self).__init__(map,self.TAG,node=node, + property = property, + description = description, + layerOrder = ','.join(layerOrder)) + + def addControl(self,**kwargs): + '''Add `LayerControl` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : LayerControl + The added element + ''' + return self.add(LayerControl,**kwargs) + def getControls(self,asdict=True): + '''Get all `LayerControl` element(s) from this + + Parameters + ---------- + asdict : bool + If `True`, return a dictonary that maps name to + `LayerControl` elements. If `False`, return a list of all + `LayerControl` children. + + Returns + ------- + children : dict or list + Dictionary or list of `LayerControl` children + + ''' + return self.getElementsByKey(LayerControl,'name',asdict) + +registerElement(PieceLayers) + +# -------------------------------------------------------------------- +class LayerControl(MapElement): + TAG=Element.MAP+'LayerControl' + CYCLE_UP='Rotate Layer Order Up' + CYCLE_DOWN='Rotate Layer Order Down' + ENABLE='Make Layer Active' + DISABLE='Make Layer Inactive' + TOGGLE='Switch Layer between Active and Inactive' + RESET='Reset All Layers' + def __init__(self,col,node=None, + name = '', + tooltip = '', + text = '', + hotkey = '', + icon = '', + canDisable = False, + propertyGate = '', #Property name, disable when property false + disabledIcon = '', + command = TOGGLE, + skip = False, + layers = [], + description = ''): + super(LayerControl,self).__init__(col,self.TAG,node=node, + name = name, + tooltip = tooltip, + text = text, + buttonText = text, + hotkey = hotkey, + icon = icon, + canDisable = canDisable, + propertyGate = propertyGate, + disabledIcon = disabledIcon, + command = command, + skip = skip, + layers = ','.join(layers), + description = description) + + def getLayers(self): + '''Get map - either a Map or WidgetMap''' + return self.getParentOfClass([PieceLayers]) + +registerElement(LayerControl) + + +# -------------------------------------------------------------------- +class LineOfSight(MapElement): + TAG=Element.MAP+'LOS_Thread' + ROUND_UP = 'Up' + ROUND_DOWN = 'Down' + ROUND_NEAREST = 'Nearest whole number' + FROM_LOCATION = 'FromLocation' + TO_LOCATION = 'ToLocation' + CHECK_COUNT = 'NumberOfLocationsChecked' + CHECK_LIST = 'AllLocationsChecked' + RANGE = 'Range' + NEVER = 'Never' + ALWAYS = 'Always' + WHEN_PERSISTENT = 'When persistent' + CTRL_CLICK = 'Cltr-Click & Drag' + + def __init__(self,map, + node=None, + threadName = 'LOS', + hotkey = key('L',ALT), + tooltip = 'Trace line of sight', + iconName = '/images/thread.gif', #'los-icon.png', + label = '', + snapLOS = False, + snapStart = True, + snapEnd = True, + report = (f'{{"Range from "+{FROM_LOCATION}' + f'+" to "+{TO_LOCATION}+" is "' + f'+{RANGE}+" (via "+{CHECK_LIST}+")"}}'), + persistent = CTRL_CLICK, + persistentIconName = '/images/thread.gif', + globl = ALWAYS, + losThickness = 3, + threadColor = rgb(255,0,0), + drawRange = True, + # rangeBg = rgb(255,255,255), + # rangeFg = rgb(0,0,0), + rangeScale = 0, + hideCounters = True, + hideOpacity = 50, + round = ROUND_UP, + canDisable = False, + propertyGate = '', + disabledIcon = ''): + '''Make Line of Sight interface + + Parameters + ---------- + threadName : str + Name of interface + hotkey : str + Start LOS key + tooltip : str + Tool tip text + iconName : str + Path to button icon + label : str + Button text + snapLOS : bool + Wether to snap both ends + snapStart : bool + Snap to start + snapEnd: bool + Snap to end + report : str + Report format + persistent : str + When persistent + persistentIconName : str + Icon when persistent(?) + globl : str + Visisble to opponents + losThickness : int + Thickness in pixels + losColor : str + Colour of line + drawRange : bool + Draw the range next to LOST thread + rangeBg : str + Range backgroung colour + rangeFg : str + Range foregrond colour + rangeScale : int + Scale of range - pixels per unit + round : str + How to round range + hideCounters :bool + If true, hide counters while making thread + hideOpacity : int + Opacity of hidden counters (percent) + canDisable : bool + IF true, then can be hidden + propertyGate : str + Name of property. When that property is TRUE, then the + interface is disabled. Must be a property name, not an expression. + disabledIcon : str + Icon to use when disabled + ''' + super(LineOfSight,self).__init__(map,self.TAG, + node = node, + threadName = threadName, + hotkey = hotkey, + tooltip = tooltip, + iconName = iconName, + label = label, + snapLOS = snapLOS, + snapStart = snapStart, + snapEnd = snapEnd, + report = report, + persistent = persistent, + persistentIconName = persistentIconName, + losThickness = losThickness, + threadColor = threadColor, + drawRange = drawRange, + #rangeBg = rangeBg, + #rangeFg = rangeFg, + rangeScale = rangeScale, + hideCounters = hideCounters, + hideOpacity = hideOpacity, + round = round, + canDisable = canDisable, + propertyGate = propertyGate, + disabledIcon = disabledIcon) + self.setAttribute('global',globl) + + +registerElement(LineOfSight) + # -------------------------------------------------------------------- class StackMetrics(MapElement): TAG=Element.MAP+'StackMetrics' @@ -1474,6 +1844,8 @@ class StackMetrics(MapElement): unexSepY = unexSepY, up = up) +registerElement(StackMetrics) + # -------------------------------------------------------------------- class ImageSaver(MapElement): TAG=Element.MAP+'ImageSaver' @@ -1491,6 +1863,9 @@ class ImageSaver(MapElement): icon = icon, propertyGate = propertyGate, tooltip = tooltip) + +registerElement(ImageSaver) + # -------------------------------------------------------------------- class TextSaver(MapElement): TAG=Element.MAP+'TextSaver' @@ -1509,6 +1884,7 @@ class TextSaver(MapElement): propertyGate = propertyGate, tooltip = tooltip) +registerElement(TextSaver) # -------------------------------------------------------------------- class ForwardToChatter(MapElement): @@ -1516,30 +1892,40 @@ class ForwardToChatter(MapElement): def __init__(self,map,node=None,**kwargs): super(ForwardToChatter,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(ForwardToChatter) + # -------------------------------------------------------------------- class MenuDisplayer(MapElement): TAG=Element.MAP+'MenuDisplayer' def __init__(self,map,node=None,**kwargs): super(MenuDisplayer,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(MenuDisplayer) + # -------------------------------------------------------------------- class MapCenterer(MapElement): TAG=Element.MAP+'MapCenterer' def __init__(self,map,node=None,**kwargs): super(MapCenterer,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(MapCenterer) + # -------------------------------------------------------------------- class StackExpander(MapElement): TAG=Element.MAP+'StackExpander' def __init__(self,map,node=None,**kwargs): super(StackExpander,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(StackExpander) + # -------------------------------------------------------------------- class PieceMover(MapElement): TAG=Element.MAP+'PieceMover' def __init__(self,map,node=None,**kwargs): super(PieceMover,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(PieceMover) + # -------------------------------------------------------------------- class SelectionHighlighters(MapElement): TAG=Element.MAP+'SelectionHighlighters' @@ -1547,12 +1933,16 @@ class SelectionHighlighters(MapElement): super(SelectionHighlighters,self).\ __init__(map,self.TAG,node=node,**kwargs) +registerElement(SelectionHighlighters) + # -------------------------------------------------------------------- class KeyBufferer(MapElement): TAG=Element.MAP+'KeyBufferer' def __init__(self,map,node=None,**kwargs): super(KeyBufferer,self).__init__(map,self.TAG,node=node,**kwargs) +registerElement(KeyBufferer) + # -------------------------------------------------------------------- class HighlightLastMoved(MapElement): TAG=Element.MAP+'HighlightLastMoved' @@ -1565,6 +1955,8 @@ class HighlightLastMoved(MapElement): enabled = enabled, thickness = thickness) +registerElement(HighlightLastMoved) + # -------------------------------------------------------------------- class CounterDetailViewer(MapElement): TAG=Element.MAP+'CounterDetailViewer' @@ -1587,7 +1979,7 @@ class CounterDetailViewer(MapElement): extraTextPadding = 0, fgColor = rgb(0,0,0), fontSize = 9, - graphicsZoom = 1.0, + graphicsZoom = 1.0,# Zoom on counters hotkey = key('\n',0), layerList = '', minDisplayPieces = 2, @@ -1649,6 +2041,8 @@ class CounterDetailViewer(MapElement): verticalTopText = verticalTopText, zoomlevel = zoomlevel) +registerElement(CounterDetailViewer) + # -------------------------------------------------------------------- class GlobalMap(MapElement): TAG=Element.MAP+'GlobalMap' @@ -1668,6 +2062,8 @@ class GlobalMap(MapElement): scale = scale, tooltip = 'Show/Hide overview window') +registerElement(GlobalMap) + # -------------------------------------------------------------------- class Zoomer(MapElement): TAG = Element.MAP+'Zoomer' @@ -1687,6 +2083,7 @@ class Zoomer(MapElement): zoomOutKey = key('-'), zoomPickKey = key('='), zoomStart = 3): + '''Zoom start is counting from the back (with default zoom levels, and zoom start, the default zoom is 1''' lvls = ','.join([str(z) for z in zoomLevels]) @@ -1707,6 +2104,8 @@ class Zoomer(MapElement): zoomPickKey = zoomPickKey, zoomStart = zoomStart) +registerElement(Zoomer) + # -------------------------------------------------------------------- class HidePiecesButton(MapElement): TAG=Element.MAP+'HidePiecesButton' @@ -1724,6 +2123,8 @@ class HidePiecesButton(MapElement): showingIcon = showingIcon, tooltip = tooltip) +registerElement(HidePiecesButton) + # -------------------------------------------------------------------- class MassKey(GlobalKey,MapElementService): TAG = Element.MAP+'MassKeyCommand' @@ -1760,6 +2161,7 @@ class MassKey(GlobalKey,MapElementService): tooltip = tooltip, icon = icon) +registerElement(MassKey) # -------------------------------------------------------------------- class Flare(MapElement): @@ -1783,10 +2185,13 @@ class Flare(MapElement): flarePulsesPerSec = flarePulsesPerSec, reportFormat = '') +registerElement(Flare) + # -------------------------------------------------------------------- class AtStart(MapElement): TAG = Element.MODULE+'map.SetupStack' - def __init__(self,map,node=None, + def __init__(self,map, + node = None, name = '', location = '', useGridLocation = True, @@ -1861,6 +2266,8 @@ class AtStart(MapElement): ''' return self.getElementsWithKey(PieceSlot,'entryName',asdict) +registerElement(AtStart) + # # EOF # @@ -1894,6 +2301,7 @@ class GlobalProperties(Element): def getProperties(self): return getElementsByKey(GlobalProperty,'name') +registerElement(GlobalProperties) # -------------------------------------------------------------------- class GlobalProperty(Element): @@ -1919,6 +2327,7 @@ class GlobalProperty(Element): def getGlobalProperties(self): return self.getParent(GlobalProperties) +registerElement(GlobalProperty) # # EOF @@ -2099,7 +2508,8 @@ class TurnTrack(TurnLevel): return [] - +registerElement(TurnTrack) + # -------------------------------------------------------------------- class TurnCounter(TurnLevel): TAG = Element.MODULE+"turn.CounterTurnLevel" @@ -2118,6 +2528,8 @@ class TurnCounter(TurnLevel): loopLimit = loopLimit, turnFormat = turnFormat) +registerElement(TurnCounter) + # -------------------------------------------------------------------- class TurnList(TurnLevel): TAG = Element.MODULE+"turn.ListTurnLevel" @@ -2135,6 +2547,8 @@ class TurnList(TurnLevel): configList = configList, turnFormat = turnFormat) +registerElement(TurnList) + # -------------------------------------------------------------------- class TurnGlobalHotkey(Element): TAG = Element.MODULE+'turn.TurnGlobalHotkey' @@ -2172,6 +2586,8 @@ class TurnGlobalHotkey(Element): '''Get the turn track''' return self.getParent(TurnTrack) +registerElement(TurnGlobalHotkey) + # # EOF # @@ -2316,6 +2732,7 @@ class Documentation(GameElement): return txt +registerElement(Documentation) # -------------------------------------------------------------------- class AboutScreen(Element): @@ -2343,6 +2760,8 @@ class AboutScreen(Element): '''Get Parent element''' return self.getParent(Documentation) +registerElement(AboutScreen) + # -------------------------------------------------------------------- class BrowserPDFFile(Element): TAG = Element.MODULE+'documentation.BrowserPDFFile' @@ -2368,6 +2787,8 @@ class BrowserPDFFile(Element): '''Get Parent element''' return self.getParent(Documentation) +registerElement(BrowserPDFFile) + # -------------------------------------------------------------------- class HelpFile(Element): TAG = Element.MODULE+'documentation.HelpFile' @@ -2400,6 +2821,8 @@ class HelpFile(Element): '''Get Parent element''' return self.getParent(Documentation) +registerElement(HelpFile) + # -------------------------------------------------------------------- class BrowserHelpFile(Element): TAG = Element.MODULE+'documentation.BrowserHelpFile' @@ -2427,7 +2850,9 @@ class BrowserHelpFile(Element): def getDocumentation(self): '''Get Parent element''' return self.getParent(Documentation) - + +registerElement(BrowserHelpFile) + # -------------------------------------------------------------------- class Tutorial(Element): TAG = Element.MODULE+'documentation.Tutorial' @@ -2468,6 +2893,8 @@ class Tutorial(Element): '''Get Parent element''' return self.getParent(Documentation) +registerElement(Tutorial) + # # EOF @@ -2517,6 +2944,8 @@ class PlayerRoster(GameElement): '''Encode for save''' return ['PLAYER\ta\ta\t'] +registerElement(PlayerRoster) + # -------------------------------------------------------------------- class PlayerSide(Element): TAG = 'entry' @@ -2540,6 +2969,8 @@ class PlayerSide(Element): '''Get Parent element''' return self.getParent(PlayerRoster) +registerElement(PlayerSide) + # # EOF @@ -2614,7 +3045,9 @@ class ChessClock(Element): def getControl(self): '''Get Parent element''' return self.getParent(ChessClockControl) - + +registerElement(ChessClock) + # ==================================================================== class ChessClockControl(GameElement): TAG=Element.MODULE+'ChessClockControl' @@ -2727,6 +3160,7 @@ class ChessClockControl(GameElement): '''Return dictionary of clocs''' return self.getElementsByKey(ChessClock,'side',asdict) +registerElement(ChessClockControl) # # EOF @@ -2961,6 +3395,8 @@ class PieceWindow(GameElement,WidgetElement): tooltip = tooltip, icon = icon) +registerElement(PieceWindow) + # -------------------------------------------------------------------- class ComboWidget(Element,WidgetElement): TAG=Element.WIDGET+'BoxWidget' @@ -2972,6 +3408,8 @@ class ComboWidget(Element,WidgetElement): width = width, height = height) +registerElement(ComboWidget) + # -------------------------------------------------------------------- class TabWidget(Element,WidgetElement): TAG=Element.WIDGET+'TabWidget' @@ -2981,6 +3419,8 @@ class TabWidget(Element,WidgetElement): node = node, entryName = entryName) +registerElement(TabWidget) + # -------------------------------------------------------------------- class ListWidget(Element,WidgetElement): TAG=Element.WIDGET+'ListWidget' @@ -2997,6 +3437,8 @@ class ListWidget(Element,WidgetElement): scale = scale, divider = divider) +registerElement(ListWidget) + # -------------------------------------------------------------------- class PanelWidget(Element,WidgetElement): TAG=Element.WIDGET+'PanelWidget' @@ -3011,6 +3453,8 @@ class PanelWidget(Element,WidgetElement): nColumns = nColumns, vert = vert) +registerElement(PanelWidget) + # -------------------------------------------------------------------- class MapWidget(Element): TAG=Element.WIDGET+'MapWidget' @@ -3046,6 +3490,8 @@ class MapWidget(Element): ''' return self.getElementsByKey(WidgetMap,'mapName',asdict=asdict) +registerElement(MapWidget) + # # EOF # @@ -3258,6 +3704,8 @@ class HexGrid(BaseGrid): width = self.getZone().getWidth() return floor(width / self.getDeltaY() + .5) +registerElement(HexGrid) + # -------------------------------------------------------------------- class SquareGrid(BaseGrid): TAG = Element.BOARD+'SquareGrid' @@ -3307,6 +3755,8 @@ class SquareGrid(BaseGrid): width = self.getZone().getWidth() return floor(width / self.getDeltaX() + .5) +registerElement(SquareGrid) + # -------------------------------------------------------------------- class HexNumbering(BaseNumbering): TAG = Element.BOARD+'mapgrid.HexGridNumbering' @@ -3368,6 +3818,8 @@ class HexNumbering(BaseNumbering): return x,y +registerElement(HexNumbering) + # -------------------------------------------------------------------- class SquareNumbering(BaseNumbering): TAG = Element.BOARD+'mapgrid.SquareGridNumbering' @@ -3395,6 +3847,7 @@ class SquareNumbering(BaseNumbering): return x,y +registerElement(SquareNumbering) # -------------------------------------------------------------------- class RegionGrid(Element): @@ -3452,6 +3905,8 @@ class RegionGrid(Element): return None +registerElement(RegionGrid) + # -------------------------------------------------------------------- class Region(Element): TAG = Element.BOARD+'Region' @@ -3527,6 +3982,8 @@ class Region(Element): return b.getMap() return None +registerElement(Region) + # # EOF # @@ -3579,7 +4036,7 @@ class ZonedGrid(Element): children : list List of `Highligter` children (even if `single=True`) ''' - return self.getAllElements(ZonedGridHighliger,single=single) + return self.getAllElements(ZonedGridHighlighter,single=single) def addZone(self,**kwargs): '''Add a `Zone` element to this @@ -3607,6 +4064,8 @@ class ZonedGrid(Element): ''' return self.getElementsByKey(Zone,'name',asdict=asdict) +registerElement(ZonedGrid) + # -------------------------------------------------------------------- class ZonedGridHighlighter(Element): TAG=Element.BOARD+'mapgrid.ZonedGridHighlighter' @@ -3614,6 +4073,96 @@ class ZonedGridHighlighter(Element): super(ZonedGridHighlighter,self).__init__(zoned,self.TAG,node=node) def getZonedGrid(self): return self.getParent(ZonedGrid) + def addZoneHighlight(self,**kwargs): + '''Add a `ZoneHighlight` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : ZoneHighlight + The added element + ''' + return self.add(ZoneHighlight,**kwargs) + def getZoneHighlights(self,asdict=True): + '''Get all ZoneHighlight element(s) from this + + Parameters + ---------- + asdict : bool + If `True`, return a dictonary that maps key to `Zone` elements. If `False`, return a list of all Zone` children. + Returns + ------- + children : dict or list + Dictionary or list of `Zone` children + ''' + return self.getElementsByKey(ZoneHighlight,'name',asdict=asdict) + +registerElement(ZonedGridHighlighter) + +# -------------------------------------------------------------------- +class ZoneHighlight(Element): + TAG=Element.BOARD+'mapgrid.ZoneHighlight' + FULL='Entire Zone', + BORDER='Zone Border', + PLAIN='Plain', + STRIPED='Striped' + CROSS='Crosshatched', + TILES='Tiled Image' + def __init__(self, + highlighters, + node = None, + name = '', + color = rgb(255,0,0), + coverage = FULL, + width = 1, + style = PLAIN, + image = '', + opacity = 50): + super(ZoneHighlight,self).__init__(highlighters, + self.TAG, + node = node, + name = name, + color = color, + coverage = coverage, + width = width, + style = style, + image = image, + opacity = int(opacity)) + def getZonedGridHighlighter(self): + return self.getParent(ZonedGridHighlighter) + + +registerElement(ZoneHighlight) + + +# -------------------------------------------------------------------- +class ZoneProperty(Element): + TAG = Element.MODULE+'properties.ZoneProperty' + def __init__(self,zone,node=None, + name = '', + initialValue = '', + isNumeric = False, + min = "null", + max = "null", + wrap = False, + description = ""): + super(ZoneProperty,self).__init__(zone,self.TAG, + node = node, + name = name, + initialValue = initialValue, + isNumeric = isNumeric, + min = min, + max = max, + wrap = wrap, + description = description) + + def getZone(self): + return self.getParent(Zone) + +registerElement(ZoneProperty) # -------------------------------------------------------------------- class Zone(Element): @@ -3693,6 +4242,19 @@ class Zone(Element): The added element ''' return self.add(RegionGrid,**kwargs) + def addProperty(self,**kwargs): + '''Add a `Property` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : Property + The added element + ''' + return self.add(ZoneProperty,**kwargs) def getHexGrids(self,single=True): '''Get all or a sole `HexGrid` element(s) from this @@ -3758,6 +4320,17 @@ class Zone(Element): if g is not None: return g return g + def getProperties(self): + '''Get all `Property` element from this + + Parameters + ---------- + Returns + ------- + children : dict + dict of `Property` children + ''' + return getElementsByKey(ZoneProperty,'name') def getPath(self): p = self['path'].split(';') @@ -3785,6 +4358,8 @@ class Zone(Element): def getYOffset(self): return self.getBB()[1] +registerElement(Zone) + # # EOF # @@ -3879,6 +4454,8 @@ class BoardPicker(MapElement): return ret +registerElement(BoardPicker) + # -------------------------------------------------------------------- class Setup(Element): TAG = 'setup' @@ -3901,7 +4478,9 @@ class Setup(Element): self.addText(txt) def getPicker(self): return self.getParent(BoardPicker) - + +registerElement(Setup) + # -------------------------------------------------------------------- class Board(Element): TAG = Element.PICKER+'Board' @@ -3982,6 +4561,7 @@ class Board(Element): return int(self['height']) return 0 +registerElement(Board) # # EOF @@ -4340,6 +4920,57 @@ class BaseMap(Element): picker = self.getPicker() if picker is None: return None return picker[0].getBoards(asdict=asdict) + def getLayers(self,asdict=True): + '''Get all `PieceLayer` element(s) from this + + Parameters + ---------- + asdict : bool + If `True`, return a dictonary that maps property name + `PieceLayers` elements. If `False`, return a list of all + `PieceLayers` children. + + Returns + ------- + children : dict or list + Dictionary or list of `PieceLayers` children + + ''' + return self.getElementsByKey(PieceLayers,'property',asdict) + def getMenus(self,asdict=True): + '''Get all Menu element(s) from this + + Parameters + ---------- + asdict : bool + If `True`, return a dictonary that maps key to `Board` + elements. If `False`, return a list of all Board` + children. + + Returns + ------- + children : dict or list + Dictionary or list of `Board` children + + ''' + return self.getElementsByKey(Menu,'name',asdict) + def getLOSs(self,asdict=True): + '''Get all Menu element(s) from this + + Parameters + ---------- + asdict : bool + If `True`, return a dictonary that maps key to `Board` + elements. If `False`, return a list of all Board` + children. + + Returns + ------- + children : dict or list + Dictionary or list of `Board` children + + ''' + return self.getElementsByKey(LineOfSight,'threadName',asdict) def addBoardPicker(self,**kwargs): '''Add a `BoardPicker` element to this @@ -4600,6 +5231,47 @@ class BaseMap(Element): The added element ''' return self.add(AtStart,**kwargs) + + + def addLayers(self,**kwargs): + '''Add `PieceLayers` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : PieceLayers + The added element + ''' + return self.add(PieceLayers,**kwargs) + def addMenu(self,**kwargs): + '''Add a `Menu` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : Menu + The added element + ''' + return self.add(Menu,**kwargs) + def addLOS(self,**kwargs): + '''Add a `Menu` element to this + + Parameters + ---------- + kwargs : dict + Dictionary of attribute key-value pairs + Returns + ------- + element : Menu + The added element + ''' + return self.add(LineOfSight,**kwargs) # -------------------------------------------------------------------- class Map(BaseMap): @@ -4657,7 +5329,9 @@ class Map(BaseMap): def getGame(self): return self.getParent(Game) - + +registerElement(Map) + # -------------------------------------------------------------------- class WidgetMap(BaseMap): TAG = Element.WIDGET+'WidgetMap' @@ -4669,6 +5343,8 @@ class WidgetMap(BaseMap): def getMapWidget(self): return self.getParent(MapWidget) +registerElement(WidgetMap) + # # EOF @@ -4721,7 +5397,7 @@ class ChartWindow(GameElement,WidgetElement): ''' return self.getElementsById(Chart,'chartName',asdict=asdict) - +registerElement(ChartWindow) # -------------------------------------------------------------------- class Chart(Element): @@ -4735,6 +5411,8 @@ class Chart(Element): description = description, fileName = fileName) +registerElement(Chart) + # # EOF # @@ -4766,7 +5444,7 @@ class Trait: this actually holds state that isn't reflected elsewhere in the DOM. This means that the data here is local to the object. So when we do - + piece = foo.getPieceSlots()[0] traits = p.getTraits() for trait in traits: @@ -5040,6 +5718,15 @@ class WithTraits(Element): Identifier ''' + last = traits[-1] + # A little hackish to use the name of the class, but needed + # because of imports into patch scripts. + if not isinstance(last,BasicTrait) and \ + not last.__class__.__name__.endswith('BasicTrait'): + from sys import stderr + print(f'Warning - last trait NOT a BasicTrait, but a {type(last)}', + file=stderr) + types = [] states = [] for trait in traits: @@ -5165,7 +5852,9 @@ class DummyWithTraits(WithTraits): if parent is not None: parent.remove(self) - + +registerElement(DummyWithTraits) + # -------------------------------------------------------------------- class PieceSlot(WithTraits): TAG = Element.WIDGET+'PieceSlot' @@ -5226,6 +5915,7 @@ class PieceSlot(WithTraits): piece.setTraits(*traits) return piece +registerElement(PieceSlot) # -------------------------------------------------------------------- class Prototype(WithTraits): @@ -5255,6 +5945,8 @@ class Prototype(WithTraits): name = name, description = description) +registerElement(Prototype) + # # EOF # @@ -5262,16 +5954,21 @@ class Prototype(WithTraits): # From traits/dynamicproperty.py # -------------------------------------------------------------------- -# Base class for property (piece or global) change traits. Encodes -# constraints and commands. +# +# class ChangePropertyTrait(Trait): DIRECT = 'P' + INCREMENT = 'I' def __init__(self, *commands, numeric = False, min = 0, max = 100, wrap = False): + '''Base class for property (piece or global) change traits. + + Encodes constraints and commands. + ''' # assert name is not None and len(name) > 0, \ # 'No name specified for ChangePropertyTriat' super(ChangePropertyTrait,self).__init__() @@ -5293,8 +5990,11 @@ class ChangePropertyTrait(Trait): # print(cmd) com = cmd[0] + ':' + cmd[1].replace(',',r'\,') + ':' + cmd[2] if cmd[2] == self.DIRECT: - com += f'\,'+cmd[3].replace(':',r'\:') + com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:') + elif cmd[2] == self.INCREMENT: + com += f'\,'+cmd[3].replace(',',r'\\,').replace(':',r'\:') cmds.append(com) + # print(cmds) return ','.join(cmds) def decodeCommands(self,commands): @@ -5305,6 +6005,8 @@ class ChangePropertyTrait(Trait): # print('parts',parts) if parts[-1][0] == self.DIRECT: parts = parts[:-1]+Trait.decodeKeys(parts[-1],',') + if parts[-1][0] == self.INCREMENT: + parts = parts[:-1]+Trait.decodeKeys(parts[-1],',') ret.append(parts) # print(commands,parts) return ret @@ -5840,7 +6542,7 @@ class NoStackTrait(Trait): canStack = False, ignoreGrid = False, description = ''): - + '''No stacking trait''' selectionOptions = (select + (self.IGNORE_GRID if ignoreGrid else '') + bandSelect) @@ -7319,6 +8021,7 @@ class Game(Element): ''' return self.getAllElements(AtStart,single) +registerElement(Game) # -------------------------------------------------------------------- class BasicCommandEncoder(GameElement): @@ -7326,6 +8029,8 @@ class BasicCommandEncoder(GameElement): def __init__(self,doc,node=None): super(BasicCommandEncoder,self).__init__(doc,self.TAG,node=node) +registerElement(BasicCommandEncoder) + # # EOF # @@ -8446,7 +9151,8 @@ class LaTeXExporter(Exporter): vassalVersion = '3.6.7', nonato = False, nochit = False, - counterScale = 1): + counterScale = 1, + resolution = 150): '''Exports a PDF and associated JSON files to a VASSAL module. Parameters @@ -8473,6 +9179,8 @@ class LaTeXExporter(Exporter): Make grids visible vassalVersion : str VASSAL version to encode this module for + resolution : int + Resolution for images (default 150) ''' self._vmodname = vmodname self._pdfname = pdfname @@ -8487,6 +9195,7 @@ class LaTeXExporter(Exporter): self._vassalVersion = vassalVersion self._nonato = nonato self._nochit = nochit + self._resolution = resolution self._counterScale = counterScale self._battleMark = 'wgBattleMarker' self._battleMarks = [] @@ -8572,6 +9281,7 @@ class LaTeXExporter(Exporter): v(f'Tutorial log: {self._tutorial}') v(f'Patch scripts: {self._patch}') v(f'Visible grids: {self._visible}') + v(f'Resolution: {self._resolution}') v(f'Scale of counters: {self._counterScale}') def setup(self): @@ -8704,6 +9414,7 @@ class LaTeXExporter(Exporter): args = ['pdftocairo', '-transp', '-singlefile', + '-r', str(self._resolution), '-f', str(page), '-l', str(page), '-png' ] @@ -8772,9 +9483,9 @@ class LaTeXExporter(Exporter): imgsinfo = self.getImagesInfo() if len(imgsinfo) - 1 != docinfo['Pages']: - raise RuntimeError(f'Number of pages in {pdfname} ' - f'(doc["Pages"]) not matched in JSON ' - f'{self._infoname} -> {len(imagesinfo)}') + raise RuntimeError(f'Number of pages in {self._pdfname} ' + f'{docinfo["Pages"]} not matched in JSON ' + f'{self._infoname} -> {len(imgsinfo)}') with VerboseGuard(f'Converting {docinfo["Pages"]} ' f'pages in {self._pdfname}') as v: @@ -9126,10 +9837,16 @@ class LaTeXExporter(Exporter): 'property': 'Phase', 'names': self._sides } }) turns.addHotkey(hotkey = self._clearMoved+'Phase', - name = 'Clear moved markers') + name = 'Clear moved markers', + reportFormat = (f'{{{self._verbose}?(' + f'"`Clear all moved markers, "+' + f'""):""}}')) if len(self._battleMarks) > 0: turns.addHotkey(hotkey = self._clearBattlePhs, - name = 'Clear battle markers') + name = 'Clear battle markers', + reportFormat = (f'{{{self._verbose}?(' + f'"`Clear all battle markers, "+' + f'""):""}}')) self._dice = self._categories\ .get('die-roll',{}) @@ -9153,7 +9870,9 @@ class LaTeXExporter(Exporter): # f'+" "' f'}}'), - resultWindow = True); + resultWindow = True, + windowX = str(int(67 * self._resolution/150)), + windowY = str(int(65 * self._resolution/150))); sdie = symb.addDie(name = die); for face, fdata in faces.items(): fn = fdata['filename'] @@ -10186,13 +10905,14 @@ class LaTeXExporter(Exporter): # ---------------------------------------------------------------- def factionTraits(self,faction): - traits = [ReportTrait(self._eliminateKey, - self._restoreKey, - self._trailKey), + offX = 36 * self._counterScale * self._resolution/150 + offY = -38 * self._counterScale * self._resolution/150 + traits = [#ReportTrait(self._eliminateKey, + # self._restoreKey, + # self._trailKey), TrailTrait(), RotateTrait(), - MovedTrait(xoff = int( 36 * self._counterScale), - yoff = int(-38 * self._counterScale)), + MovedTrait(xoff = int(offX),yoff = int(offY)), DeleteTrait(), SendtoTrait(mapName = 'DeadMap', boardName = f'{faction} pool', @@ -11308,7 +12028,10 @@ class LaTeXExporter(Exporter): pc = p["coords"] if j == 0: vv(f'',end='') vv(f'[{pn}] ',end='',flush=True,noindent=True) - + + if pn.endswith(' flipped'): + pn = pn[:-len(' flipped')] + x, y = tran(*pc) r = grid.addRegion(name = pn, originx = x, @@ -11499,7 +12222,7 @@ class LaTeXExporter(Exporter): def addDie(self): '''Add a `Die` element to the module ''' - if self._dice is not None: + if self._dice is not None and len(self._dice) > 0: return self._game.addDiceButton(name = '1d6', hotkey = self._diceKey) @@ -11568,6 +12291,9 @@ if __name__ == '__main__': ap.add_argument('-S','--counter-scale', type=float, default=1, help='Scale counters by factor') + ap.add_argument('-R','--resolution', + type=int, default=150, + help='Resolution of images') args = ap.parse_args() @@ -11600,6 +12326,7 @@ if __name__ == '__main__': vassalVersion = args.vassal_version, nonato = args.no_nato_prototypes, nochit = args.no_chit_information, + resolution = args.resolution, counterScale = args.counter_scale) exporter.run() except Exception as e: -- cgit v1.2.3