texlive[69960] Master/texmf-dist: randexam (18feb24)

commits+karl at tug.org commits+karl at tug.org
Sun Feb 18 22:04:44 CET 2024


Revision: 69960
          https://tug.org/svn/texlive?view=revision&revision=69960
Author:   karl
Date:     2024-02-18 22:04:44 +0100 (Sun, 18 Feb 2024)
Log Message:
-----------
randexam (18feb24)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf
    trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex
    trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf
    trunk/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf
    trunk/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf
    trunk/Master/texmf-dist/doc/latex/randexam/randexam.pdf
    trunk/Master/texmf-dist/doc/latex/randexam/randexam.tex
    trunk/Master/texmf-dist/tex/latex/randexam/randexam.cls

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex	2024-02-18 18:26:01 UTC (rev 69959)
+++ trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-answer.tex	2024-02-18 21:04:44 UTC (rev 69960)
@@ -2,7 +2,7 @@
 % !TEX program = xelatex
 \documentclass[12pt,math=all]{randexam}
 
-%\boolfalse{exam at answer} % hide answers
+%\SetExamBoolFalse{answer} % hide answers
 
 \SetExamOption{
   seed = 19061116, % random seed
@@ -14,7 +14,7 @@
 
 \gradetable[total=4]
 
-\exampart{Fill in the blanks.}{6 questions; 3 points for each; 18 points in total.}
+\exampart{Fill in the blanks.}[6 questions; 3 points for each; 18 points in total.]
 
 % make answer table: six in total, three for each row, strut height 3em
 \answertable[total=6,column=3,strut=3em]
@@ -71,7 +71,7 @@
 
 \newpage
 
-\exampart{Select one answer from four choices.}{6 questions; 3 points for each; 18 points in total.}
+\exampart{Select one answer from four choices.}[6 questions; 3 points for each; 18 points in total.]
 
 % make answer table: six in total, six for each row, default strut height
 \answertable[total=6,column=6]
@@ -170,7 +170,7 @@
 
 \newpage
 
-\exampart{Work out math questions.}{6 questions; 8 points for each; 48 points in total.}
+\exampart{Work out math questions.}[6 questions; 8 points for each; 48 points in total.]
 
 \begin{question}
 The first question $\int\e^{2x}\,(\tan x+1)^2\dx$.
@@ -307,7 +307,7 @@
 
 \newpage
 
-\exampart{Work out math proofs.}{2 questions; 16 points in total.}
+\exampart{Work out math proofs.}[2 questions; 16 points in total.]
 
 \SetExamTranslation{solution-Solution=Proof} % rename "Solution" as "Proof"
 

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam-a-blank.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam-b-answer.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam-b-blank.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/randexam/randexam.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/randexam/randexam.tex	2024-02-18 18:26:01 UTC (rev 69959)
+++ trunk/Master/texmf-dist/doc/latex/randexam/randexam.tex	2024-02-18 21:04:44 UTC (rev 69960)
@@ -3,7 +3,7 @@
 \documentclass[12pt,plain,math=most]{randexam}
 \geometry{b5paper,margin=2cm}
 
-\newcommand*{\myversion}{2024D}
+\newcommand*{\myversion}{2024E}
 \newcommand*{\mydate}{\the\year-\mylpad\month-\mylpad\day}
 \newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
 
@@ -30,8 +30,6 @@
 \usepackage{tabularx}
 \usepackage{booktabs}
 
-\newcommand{\fillbox}[1]{\ulinefill{#1}\underline{#1}\ulinefill{#1}}
-
 \usepackage{fancyvrb}
 
 \DefineVerbatimEnvironment{code}{Verbatim}{%
@@ -56,10 +54,10 @@
   \noindent\Large
   \begin{tabularx}{\linewidth}{|X|}
     \hline
-    Title: \fillbox{\color{blue3}The randexam class for LaTeX}\\
-    Author: \fillbox{Jianrui Lyu (tolvjr at 163.com)}\\
-    Version: \fillbox{\myversion{} (\mydate)}\\
-    Code: \fillbox{\url{https://github.com/lvjr/randexam}}\\
+    Title:   \ExamFillUlineText{\color{blue3}The randexam class for LaTeX}\\
+    Author:  \ExamFillUlineText{Jianrui Lyu (tolvjr at 163.com)}\\
+    Version: \ExamFillUlineText{\myversion{} (\mydate)}\\
+    Code:    \ExamFillUlineText{\url{https://github.com/lvjr/randexam}}\\
     \hline
   \end{tabularx}%
 }
@@ -110,11 +108,11 @@
 \begin{code}
 \examtitle{name=Math Final Exam,date=2018-06-28,version=A}
 ......
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
 ......
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
 ......
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
 ......
 \examdata{Some data may be used in the exam}
 ......
@@ -138,11 +136,11 @@
 The questions in an exam could be separated into several parts:
 
 \begin{code}
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
 ......
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
 ......
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
 ......
 \end{code}
 
@@ -163,7 +161,7 @@
 \subsection{True-or-false questions}
 
 \begin{code}
-\exampart{True-or-false questions}{3 points for each.}
+\exampart{True-or-false questions}[3 points for each.]
 
 \begin{question}
 The first true-or-false question. \tickout{T}
@@ -192,7 +190,7 @@
 \subsection{Fill-in-the-blank questions}
 
 \begin{code}
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
 
 \begin{question}
 The first fill-in-the-blank question \fillout{answer}.
@@ -220,7 +218,7 @@
 \subsection{Multiple-choice questions}
 
 \begin{code}
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
 
 \begin{question}
 The first multiple-choice questions \pickout{A}.
@@ -278,7 +276,7 @@
 For subjective questions, you could put answers inside \myenv{solution} environment.
 
 \begin{code}
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
 
 \begin{question}
 The first math calculation question.
@@ -318,7 +316,7 @@
 You can write other types of questions. For example:
 
 \begin{code}
-\exampart{Some question type}{4 points for each.}
+\exampart{Some question type}[4 points for each.]
 
 \begin{question}
 First question text. \answer{Answer text.}
@@ -522,7 +520,8 @@
   \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 \\
+  \myopt{language}   & set language and use corresponding translations \\
+ %\myopt{chinese}    & select Chinese language and load \mypkg{ctex} package \\
 \bottomrule
 \end{tabularx}
 
@@ -651,6 +650,27 @@
 
 This command is useful in defining new templates for the exam (see Subsection \ref{subsect:template}).
 
+\subsection{Checking current language}
+
+There are commands \mycmd{\IfExamLanguageEqT},
+\mycmd{\IfExamLanguageEqF}, and \mycmd{\IfExamLanguageEqTF},
+with which you can execute code based on current language.
+
+\subsection{Checking boolean flags}
+
+There are several commands for creating, setting, or checking boolean flags:
+
+\begin{tabularx}{\linewidth}{@{}lX@{}}
+\toprule
+  \mycmd{\NewExamBool}      & create a new boolean flag \\
+  \mycmd{\SetExamBoolTrue}  & set the boolean flag to true \\
+  \mycmd{\SetExamBoolFalse} & set the boolean flag to false \\
+  \mycmd{\IfExamBoolT}      & run code if the boolean flag is true \\
+  \mycmd{\IfExamBoolF}      & run code if the boolean flag is false \\
+  \mycmd{\IfExamBoolTF}     & run true-state code or false-state code \\
+\bottomrule
+\end{tabularx}
+
 \subsection{Saving and reading key values}
 
 With \mycmd{\SetExamValue} and \mycmd{\UseExamValue} you could save and read
@@ -667,10 +687,15 @@
 \hrule
 \vspace{0.5em}
 
-The \mypkg{randexam} class also provides commands \mycmd{\IfExamValueExistT},
-\mycmd{\IfExamValueExistF}, and \mycmd{\IfExamValueExistTF},
-with which you can do conditional typesetting.
+The class also provides commands for conditional typesetting.
 
+\begin{tabularx}{\linewidth}{@{}XXX@{}}
+\toprule
+\mycmd{\IfExamValueExistT} & \mycmd{\IfExamValueExistF} & \mycmd{\IfExamValueExistTF} \\
+\mycmd{\IfExamValueEmptyT} & \mycmd{\IfExamValueEmptyF} & \mycmd{\IfExamValueEmptyTF} \\
+\bottomrule
+\end{tabularx}
+
 \begin{code}
 \IfExamValueExistTF{somemodule}{somekey}{True}{False}
 \end{code}
@@ -763,4 +788,77 @@
 \end{tabularx}\par
 \endgroup
 
+\subsection{Filling space with contents}
+
+In defining exam templates, we may need the following filling commands.
+
+\begin{tabularx}{\linewidth}{@{}lX@{}}
+\toprule
+  \mycmd{\ExamFillCdot}         & fill space with centered dots \\
+  \mycmd{\ExamFillUline}        & fill space with an underline \\
+  \mycmd{\ExamFillUlineText}    & fill space with underlined text \\
+  \mycmd{\ExamFillUlinePhantom} & fill space with underlined phantom text \\
+\bottomrule
+\end{tabularx}
+
+\begin{code}
+Hello\ExamFillCdot World\par
+Hello\ExamFillUline World\par
+Hello\ExamFillUlineText{Text}World\par
+Hello\ExamFillUlinePhantom{\Huge Text}World\par
+\end{code}
+
+Hello\ExamFillCdot World\par
+Hello\ExamFillUline World\par
+Hello\ExamFillUlineText{Text}World\par
+Hello\ExamFillUlinePhantom{\Huge Text}World\par
+
+\subsection{Headers and Footers}
+
+To customize headers and footers of the exam paper,
+we could modify the following \myval{fancy} templates.
+
+\begin{code}
+\DeclareExamTemplate{headleft}{fancy}{
+  \UseExamValue{examtitle}{name}
+}
+\DeclareExamTemplate{headcenter}{fancy}{}
+\DeclareExamTemplate{headright}{fancy}{
+  \IfExamBoolTF{answer}{
+    \UseExamTranslation{headfoot-Solutions}
+  }{
+    \UseExamTranslation{headfoot-Name}:\hspace{12em}
+  }
+}
+\DeclareExamTemplate{footleft}{fancy}{
+  \UseExamValue{examtitle}{date}
+}
+\DeclareExamTemplate{footcenter}{fancy}{
+  \UseExamTranslation{headfoot-Page} \thepage\space
+  \UseExamTranslation{headfoot-of} \zpageref{LastPage}
+}
+\DeclareExamTemplate{footright}{fancy}{
+  \UseExamTranslation{headfoot-Version}
+  \UseExamValue{examtitle}{version}
+}
+\end{code}
+
+Actually, \mypkg{randexam} class uses \mypkg{fancyhdr} package
+to customize headers and footers.
+
+\subsection{Themes of exam papers}
+
+With \mycmd{\DeclareExamTheme} command you can collect some templates into a theme,
+which could be activated later with \mycmd{\SelectExamTheme} command.
+
+\begin{code}
+\DeclareExamTheme{mytheme}{
+  \SelectExamTemplate{examtitle}{mytheme}
+  \SelectExamTemplate{exampart}{mytheme}
+  \SelectExamTemplate{examdata}{mytheme}
+}
+......
+\SelectExamTheme{mytheme}
+\end{code}
+
 \end{document}

Modified: trunk/Master/texmf-dist/tex/latex/randexam/randexam.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/randexam/randexam.cls	2024-02-18 18:26:01 UTC (rev 69959)
+++ trunk/Master/texmf-dist/tex/latex/randexam/randexam.cls	2024-02-18 21:04:44 UTC (rev 69960)
@@ -6,7 +6,7 @@
 % ----------------------------------------------------------------------------
 
 \NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{randexam}[2024-02-03 v2024D Make an exam paper and its randomized variants]
+\ProvidesClass{randexam}[2024-02-18 v2024E Make an exam paper and its randomized variants]
 
 %% Old LaTeX release could not recognize date format like 2022-11-01
 %\@ifl at t@r\fmtversion{2022-11-01}{}{
@@ -25,27 +25,74 @@
 \IgnoreSpacesOn
 
 %% ---------------------------------------------------------------------------
-%% Declare class options
+%% Boolean commands for this class
 %% ---------------------------------------------------------------------------
 
 \RequirePackage{etoolbox}
 
-\newbool{exam at plain}      \boolfalse{exam at plain}      % use plain page style
-\newbool{exam at twoinone}   \boolfalse{exam at twoinone}   % use A3 paper
-\newbool{exam at oneside}    \boolfalse{exam at oneside}    % use single sided exam paper
-\newbool{exam at resetnumber}\booltrue{exam at resetnumber} % reset numbers in new exam parts
-\newbool{exam at random}     \boolfalse{exam at random}     % shuffle questions
-\newbool{exam at answer}     \booltrue{exam at answer}      % show answers
-\newbool{exam at evaluator}  \boolfalse{exam at evaluator}  % add evaluator line in the grade table
-\newbool{exam at mathdesign} \booltrue{exam at mathdesign}  % use mathdesign fonts
-\newbool{exam at freealign}  \boolfalse{exam at freealign}  % load freealign package
-\newbool{exam at medmath}    \boolfalse{exam at medmath}    % use medium-size formulas
-\newbool{exam at moremath}   \boolfalse{exam at moremath}   % define more math commands
+\NewDocumentCommand\NewExamBool{m}{
+  \newbool{exam@#1}
+}
 
+\NewDocumentCommand\SetExamBoolTrue{m}{
+  \booltrue{exam@#1}
+}
+
+\NewDocumentCommand\SetExamBoolFalse{m}{
+  \boolfalse{exam@#1}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolT{m+m}{
+  \ifbool{exam@#1}{#2}{}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolF{m+m}{
+  \ifbool{exam@#1}{}{#2}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolTF{m+m+m}{
+  \ifbool{exam@#1}{#2}{#3}
+}
+
+%% ---------------------------------------------------------------------------
+%% Declare language commands
+%% ---------------------------------------------------------------------------
+
+\tlSet\l at rdxm@current at language@tl{english}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqT{m+m}{
+  \ExpandArgs{V}\ifstrequal\l at rdxm@current at language@tl{#1}{#2}{}
+}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqF{m+m}{
+  \ExpandArgs{V}\ifstrequal\l at rdxm@current at language@tl{#1}{}{#2}
+}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqTF{m+m+m}{
+  \ExpandArgs{V}\ifstrequal\l at rdxm@current at language@tl{#1}{#2}{#3}
+}
+
+%% ---------------------------------------------------------------------------
+%% Declare class options
+%% ---------------------------------------------------------------------------
+
+\NewExamBool{plain}      \SetExamBoolFalse{plain}      % use plain page style
+\NewExamBool{twoinone}   \SetExamBoolFalse{twoinone}   % use A3 paper
+\NewExamBool{oneside}    \SetExamBoolFalse{oneside}    % use single sided exam paper
+\NewExamBool{resetnumber}\SetExamBoolTrue{resetnumber} % reset numbers in new exam parts
+\NewExamBool{random}     \SetExamBoolFalse{random}     % shuffle questions
+\NewExamBool{answer}     \SetExamBoolTrue{answer}      % show answers
+\NewExamBool{evaluator}  \SetExamBoolFalse{evaluator}  % add evaluator line in the grade table
+\NewExamBool{mathdesign} \SetExamBoolTrue{mathdesign}  % use mathdesign fonts
+\NewExamBool{freealign}  \SetExamBoolFalse{freealign}  % load freealign package
+\NewExamBool{medmath}    \SetExamBoolFalse{medmath}    % use medium-size formulas
+\NewExamBool{moremath}   \SetExamBoolFalse{moremath}   % define more math commands
+
 \DeclareKeys[randexam]{
-   plain      .if        = exam at plain
+   language   .store     = \l at rdxm@current at language@tl
+  ,plain      .if        = exam at plain
   ,a3paper    .if        = exam at twoinone
-  ,a3input    .code      = \booltrue{exam at twoinone}\booltrue{exam at plain}
+  ,a3input    .code      = \SetExamBoolTrue{twoinone}\SetExamBoolTrue{plain}
   ,oneside    .if        = exam at oneside
   ,random     .if        = exam at random
   ,noanswer   .ifnot     = exam at answer
@@ -56,17 +103,17 @@
   ,moremath   .if        = exam at moremath
   ,math       .choice:
   ,math       .default:n = many
-  ,math/many  .code      = \booltrue{exam at mathdesign}\booltrue{exam at freealign}
-  ,math/most  .code      = \booltrue{exam at mathdesign}\booltrue{exam at freealign}
-                           \booltrue{exam at medmath}
-  ,math/all   .code      = \booltrue{exam at mathdesign}\booltrue{exam at freealign}
-                           \booltrue{exam at medmath}\booltrue{exam at moremath}
+  ,math/many  .code      = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+  ,math/most  .code      = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+                           \SetExamBoolTrue{medmath}
+  ,math/all   .code      = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+                           \SetExamBoolTrue{medmath}\SetExamBoolTrue{moremath}
 }
 
 %% Support for Chinese language
-\newbool{exam at ctex}     \boolfalse{exam at ctex}      % load ctex package
-\newbool{exam at solidot}  \boolfalse{exam at solidot}   % use full-width solid periods
-\newbool{exam at sourcehan}\boolfalse{exam at sourcehan} % use source han font
+\NewExamBool{ctex}     \SetExamBoolFalse{ctex}      % load ctex package
+\NewExamBool{solidot}  \SetExamBoolFalse{solidot}   % use full-width solid periods
+\NewExamBool{sourcehan}\SetExamBoolFalse{sourcehan} % use source han font
 \DeclareKeys[randexam]{
    ctex         .if        = exam at ctex
   ,solidot      .if        = exam at solidot
@@ -73,9 +120,9 @@
   ,sourcehan    .if        = exam at sourcehan
   ,chinese      .choice:
   ,chinese      .default:n = many
-  ,chinese/many .code      = \booltrue{exam at ctex}
-  ,chinese/most .code      = \booltrue{exam at ctex}\booltrue{exam at solidot}
-  ,chinese/all  .code      = \booltrue{exam at ctex}\booltrue{exam at solidot}\booltrue{exam at sourcehan}
+  ,chinese/many .code      = \SetExamBoolTrue{ctex}
+  ,chinese/most .code      = \SetExamBoolTrue{ctex}\SetExamBoolTrue{solidot}
+  ,chinese/all  .code      = \SetExamBoolTrue{ctex}\SetExamBoolTrue{solidot}\SetExamBoolTrue{sourcehan}
 }
 
 \DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{article}}
@@ -84,12 +131,18 @@
 
 \LoadClass{article}
 
-\ifbool{exam at twoinone}{
+%% Avoid option conflicts with fontspec package
+%% see https://github.com/latex3/fontspec/issues/501
+\let\@raw at classoptionslist\@empty
+
+\IfExamBoolTF{twoinone}{
   \RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
 }{
   \RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
 }
 
+\geometry{headheight=17pt}
+
 \RequirePackage{amsmath}
 \RequirePackage{array}
 \RequirePackage{calc}
@@ -100,10 +153,12 @@
 \RequirePackage{zref-user,zref-lastpage}
 \RequirePackage{tabularx}
 \RequirePackage{xcolor}
+\RequirePackage{tabularray}
+\UseTblrLibrary{diagbox}
 
-\ifbool{exam at plain}{\allowdisplaybreaks[4]}{}
+\IfExamBoolT{plain}{\allowdisplaybreaks[4]}
 
-\ifbool{exam at twoinone}{
+\IfExamBoolT{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;
@@ -111,9 +166,9 @@
   % 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 at mathdesign}{
+\IfExamBoolTF{mathdesign}{
   \RequirePackage[utopia]{mathdesign} % charter, utopia
   \renewcommand\bfdefault{bx}
   \let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
@@ -122,6 +177,7 @@
   \RequirePackage{amssymb}
 }
 
+\setlength\arraycolsep{4pt}
 \newcolumntype{Y}{>{\centering\arraybackslash}X}
 \newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}}
 
@@ -157,8 +213,6 @@
 %% Translation commands for exam keywords
 %% ---------------------------------------------------------------------------
 
-\tlSet\l at rdxm@current at language@tl{english}
-
 \DeclareUnknownKeyHandler[randexam/translation]{
   \tlSet{\expName{l at rdxm@translate@\l at rdxm@declare at language@tl @#1 at tl}}{#2}
 }
@@ -223,7 +277,7 @@
   ,solution-Solution    = Solution
 }
 
-\SelectExamTranslation{english}
+\ExpandArgs{V}\SelectExamTranslation\l at rdxm@current at language@tl
 
 %% ---------------------------------------------------------------------------
 %% Keyvalue commands for exam elements
@@ -257,6 +311,16 @@
   \UseName{l at rdxm@value@#1@#2 at tl}
 }
 
+\NewExpandableDocumentCommand\IfExamValueEmptyT{mm+m}{
+  \ifcsempty{l at rdxm@value@#1@#2 at tl}{#3}{}
+}
+\NewExpandableDocumentCommand\IfExamValueEmptyF{mm+m}{
+  \ifcsempty{l at rdxm@value@#1@#2 at tl}{}{#3}
+}
+\NewExpandableDocumentCommand\IfExamValueEmptyTF{mm+m+m}{
+  \ifcsempty{l at rdxm@value@#1@#2 at tl}{#3}{#4}
+}
+
 %% 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}{
@@ -275,6 +339,44 @@
 }
 
 %% ---------------------------------------------------------------------------
+%% Theme commands for exam papers
+%% ---------------------------------------------------------------------------
+
+%% #1: theme name; #2: theme code
+\NewDocumentCommand\DeclareExamTheme{m+m}{
+  \tlSet{\expName{l at rdxm@theme@#1 at tl}}{#2}
+}
+
+%% #1: theme name
+\NewDocumentCommand\SelectExamTheme{m}{
+  \UseName{l at rdxm@theme@#1 at tl}
+}
+
+\DeclareKeys[randexam]{
+  theme .code = \SelectExamTheme{#1}
+}
+
+%% ---------------------------------------------------------------------------
+%% Fill commands for exam papers
+%% ---------------------------------------------------------------------------
+
+\NewDocumentCommand\ExamFillCdot{}{
+  \leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax
+}
+
+\NewDocumentCommand\ExamFillUline{}{
+  \xleaders\hbox{\underline{\kern1pt}}\hfill\kern0pt
+}
+
+\NewDocumentCommand\ExamFillUlinePhantom{m}{
+  \xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt
+}
+
+\NewDocumentCommand\ExamFillUlineText{m}{
+  \ExamFillUlinePhantom{#1}\underline{#1}\ExamFillUlinePhantom{#1}
+}
+
+%% ---------------------------------------------------------------------------
 %% Command for exam title: \examtitle
 %% ---------------------------------------------------------------------------
 
@@ -289,7 +391,7 @@
 \DeclareExamTemplate{examtitle}{normal}{
   \begingroup
   \Large\noindent
-  \ifbool{exam at answer}{
+  \IfExamBoolTF{answer}{
     \textcolor{red!80!black}{
       \UseExamValue{examtitle}{name}\hfill\UseExamTranslation{examtitle-Solutions}
     }
@@ -302,8 +404,8 @@
 
 \NewDocumentCommand\examtitle{+m}{
   \SetExamValue{examtitle}{#1}
-  \thispagestyle{plain}
-  \ifbool{exam at random}{
+  \IfExamBoolF{plain}{\thispagestyle{fancyfirst}}
+  \IfExamBoolT{random}{
     \tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{A}{
       \SetExamValue{examtitle}{version=B}
     }
@@ -310,7 +412,7 @@
     \tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{C}{
       \SetExamValue{examtitle}{version=D}
     }
-  }{}
+  }
   \UseExamTemplate{examtitle}{default}
 }
 
@@ -360,7 +462,7 @@
     {}
     {\UseExamValue{gradetable}{total}}
     \rdxm at gobble@one
-  \ifbool{exam at evaluator}{
+  \IfExamBoolT{evaluator}{
     \rdxm at table@make at row
       \l at rdxm@gradetable at evaluator@tl
       {\textbf{\UseExamTranslation{gradetable-Evaluator}}
@@ -368,13 +470,13 @@
       {}
       {\UseExamValue{gradetable}{total}}
       \rdxm at gobble@one
-  }{}
+  }
   \noindent
   \begin{tabularx}{\linewidth}{|c|*{\UseExamValue{gradetable}{total}}{Y|}Y|}
     \hline
     \l at rdxm@gradetable at part@tl \\ \hline
     \l at rdxm@gradetable at score@tl \\ \hline
-    \ifbool{exam at evaluator}{\l at rdxm@gradetable at evaluator@tl \\ \hline}{}
+    \IfExamBoolT{evaluator}{\l at rdxm@gradetable at evaluator@tl \\ \hline}
   \end{tabularx}
 }
 \SelectExamTemplate{gradetable}{normal}
@@ -391,56 +493,115 @@
 %% Setting header and footer
 %% ---------------------------------------------------------------------------
 
-\newcommand{\rdxm at columnbox}[1]{\makebox[\columnwidth]{#1}}
-\newcommand{\rdxm at headleft}{\UseExamValue{examtitle}{name}}
-\newcommand{\rdxm at headright}{
-  \ifbool{exam at answer}{
+\DeclareExamTemplate{headleft}{empty}{}
+\DeclareExamTemplate{headcenter}{empty}{}
+\DeclareExamTemplate{headright}{empty}{}
+\DeclareExamTemplate{footleft}{empty}{}
+\DeclareExamTemplate{footcenter}{empty}{}
+\DeclareExamTemplate{footright}{empty}{}
+
+\DeclareExamTemplate{headleft}{plain}{}
+\DeclareExamTemplate{headcenter}{plain}{}
+\DeclareExamTemplate{headright}{plain}{}
+\DeclareExamTemplate{footleft}{plain}{}
+\DeclareExamTemplate{footcenter}{plain}{\thepage}
+\DeclareExamTemplate{footright}{plain}{}
+
+\DeclareExamTemplate{headleft}{fancy}{
+  \UseExamValue{examtitle}{name}
+}
+\DeclareExamTemplate{headcenter}{fancy}{}
+\DeclareExamTemplate{headright}{fancy}{
+  \IfExamBoolTF{answer}{
     \UseExamTranslation{headfoot-Solutions}
   }{
     \UseExamTranslation{headfoot-Name}:\hspace{12em}
   }
 }
-\newcommand{\rdxm at headtext}{\rdxm at headleft\hfill\rdxm at headright}
-\newcommand{\rdxm at footleft}{\UseExamValue{examtitle}{date}}
-\newcommand{\rdxm at footcenter}{
+\DeclareExamTemplate{footleft}{fancy}{
+  \UseExamValue{examtitle}{date}
+}
+\DeclareExamTemplate{footcenter}{fancy}{
   \MakeExamNameNumber{\UseExamTranslation{headfoot-Page}}{\thepage}
   \space
   \MakeExamNameNumber{\UseExamTranslation{headfoot-of}}{\zpageref{LastPage}}
 }
-\newcommand{\rdxm at footright}{
+\DeclareExamTemplate{footright}{fancy}{
   \MakeExamNameNumber{\UseExamTranslation{headfoot-Version}}
       {\UseExamValue{examtitle}{version}}
 }
-\newcommand{\rdxm at foottext}{\rdxm at footleft\hfill\rdxm at footcenter\hfill\rdxm at footright}
 
-% fancy page style
-\fancyhf{} % clear head and foot
-\ifbool{exam at twoinone}{
-  \renewcommand{\headrulewidth}{0pt}
-  \lhead{\small\underline{\rdxm at columnbox{\rdxm at headtext}\strut}}
-  \rhead{\small\underline{\rdxm at columnbox{\rdxm at headtext}\strut}}
-  \lfoot{\small\rdxm at columnbox{\rdxm at foottext}}
-  \rfoot{\small\rdxm at columnbox{\stepcounter{page}\rdxm at foottext}}
+\tlSet\l at rdxm@headtext at tl{
+  \UseExamTemplate{headleft}{default}
+  \hfill
+  \UseExamTemplate{headcenter}{default}
+  \hfill
+  \UseExamTemplate{headright}{default}
+}
+
+\tlSet\l at rdxm@foottext at tl{
+  \UseExamTemplate{footleft}{default}
+  \hfill
+  \UseExamTemplate{footcenter}{default}
+  \hfill
+  \UseExamTemplate{footright}{default}
+}
+
+\newrobustcmd\rdxm at columnbox[1]{\makebox[\columnwidth]{#1}}
+
+\newrobustcmd\rdxm at other@pages at only[1]{\ifnumgreater{\value{page}}{1}{#1}{}}
+\newrobustcmd\rdxm at fancyhead[2][]{\fancyhead[#1]{\rdxm at other@pages at only{#2}}}
+\newrobustcmd\rdxm at fancyfoot[2][]{\fancyfoot[#1]{\rdxm at other@pages at only{#2}}}
+
+\IfExamBoolTF{twoinone}{
+  \rdxm at fancyhead[L]{\small\underline{\rdxm at columnbox{\l at rdxm@headtext at tl}\strut}}
+  \fancyhead[C]{}
+  \fancyhead[R]{\small\underline{\rdxm at columnbox{\l at rdxm@headtext at tl}\strut}}
+  \fancyfoot[L]{\small\rdxm at columnbox{\l at rdxm@foottext at tl}}
+  \fancyfoot[C]{}
+  \fancyfoot[R]{\small\rdxm at columnbox{\stepcounter{page}\l at rdxm@foottext at tl}}
 }{
-  \lhead{\small\rdxm at headleft}
-  \rhead{\small\rdxm at headright}
-  \cfoot{\small\rdxm at foottext}
+  \rdxm at fancyhead[L]{\small\UseExamTemplate{headleft}{default}}
+  \rdxm at fancyhead[C]{\small\UseExamTemplate{headcenter}{default}}
+  \rdxm at fancyhead[R]{\small\UseExamTemplate{headright}{default}}
+  \fancyfoot[L]{\small\UseExamTemplate{footleft}{default}}
+  \fancyfoot[C]{\small\UseExamTemplate{footcenter}{default}}
+  \fancyfoot[R]{\small\UseExamTemplate{footright}{default}}
 }
 
-% plain page style
+%% plain page style
 \fancypagestyle{plain}{
-  \renewcommand{\headrulewidth}{0pt}
-  \fancyhf{}
-  \ifbool{exam at twoinone}{
-    \rhead{\small\underline{\rdxm at columnbox{\rdxm at headtext\strut}}}
-    \lfoot{\small\rdxm at columnbox{\rdxm at foottext}}
-    \rfoot{\small\rdxm at columnbox{\stepcounter{page}\rdxm at foottext}}
+  \renewcommand\headrulewidth{0pt}
+  \fancyhead{}
+  \SelectExamTemplate{footleft}{plain}
+  \SelectExamTemplate{footcenter}{plain}
+  \SelectExamTemplate{footright}{plain}
+}
+
+%% fancy page style
+\tlSet\l at rdxm@fancy at page@code at tl{
+  \SelectExamTemplate{headleft}{fancy}
+  \SelectExamTemplate{headcenter}{fancy}
+  \SelectExamTemplate{headright}{fancy}
+  \SelectExamTemplate{footleft}{fancy}
+  \SelectExamTemplate{footcenter}{fancy}
+  \SelectExamTemplate{footright}{fancy}
+}
+\fancypagestyle{fancy}{
+  \IfExamBoolTF{twoinone}{
+    \renewcommand\headrulewidth{0pt}
   }{
-    \cfoot{\small\rdxm at foottext}
+    \renewcommand\headrulewidth{0.4pt}
   }
+  \l at rdxm@fancy at page@code at tl
 }
+\fancypagestyle{fancyfirst}{
+  \renewcommand\headrulewidth{0pt}
+  \l at rdxm@fancy at page@code at tl
+}
 
-\ifbool{exam at plain}{\pagestyle{plain}}{\pagestyle{fancy}}
+%% set page style at this time since users may change header/footer templates
+\AtBeginDocument{\IfExamBoolTF{plain}{\pagestyle{plain}}{\pagestyle{fancy}}}
 
 %% ---------------------------------------------------------------------------
 %% Class option for shuffling questions: random
@@ -454,7 +615,7 @@
   seed .initial:n = 19061116
 }
 
-\ifbool{exam at random}{
+\IfExamBoolT{random}{
   \RequirePackage{pgf}
   \RequirePackage{pgffor}
   \newcommand*\exam at set@seed{
@@ -465,7 +626,7 @@
     \pgfmathsetseed{\rdxm at random@seed}
     \pgfmathrandominteger\rdxm at random@seed{1}{2147483647}
   }
-}{}
+}
 
 %% ---------------------------------------------------------------------------
 %% Command for exam groups: \exampart
@@ -481,7 +642,7 @@
 \SetExamValue{exampart}{number=\Roman}
 
 %% No displaying question number when there is only one question in the part
-\newbool{exam at onlyonequestion}\boolfalse{exam at onlyonequestion}
+\NewExamBool{onlyonequestion}\SetExamBoolFalse{onlyonequestion}
 
 \xdef\allquestions{}
 \xdef\lastquestion{}
@@ -564,12 +725,12 @@
 }
 
 \newcommand{\printquestions}{
-  \ifbool{exam at random}{
+  \IfExamBoolT{random}{
     \rdxm at appto@questions
     \rdxm at shuffle@questions
     \setcounter{question}{0}
     \allquestions
-  }{}
+  }
   \xdef\allquestions{}
   \xdef\lastquestion{}
 }
@@ -582,11 +743,13 @@
     }
     :~\UseExamValue{exampart}{type}
   }
-  \space(\UseExamValue{exampart}{points})
+  \IfExamValueEmptyF{exampart}{points}{
+    \space(\UseExamValue{exampart}{points})
+  }
 }
 \SelectExamTemplate{exampart}{normal}
 
-\newcommand{\exampart}[2]{
+\NewDocumentCommand\exampart{+m+O{}}{
   \printquestions
   \setcounter{totalquestions}{\value{totalquestions}+\value{question}}
   \setcounter{question}{0}
@@ -598,9 +761,9 @@
   \endgroup
   \par\nopagebreak
   \if\relax\detokenize{#1}\relax % #1 is empty
-    \booltrue{exam at onlyonequestion}
+    \SetExamBoolTrue{onlyonequestion}
   \else
-    \boolfalse{exam at onlyonequestion}
+    \SetExamBoolFalse{onlyonequestion}
     \vspace{1em}
   \fi
   % \@afterheading sets \@nobreaktrue, which will prevent page breaks before lists;
@@ -649,8 +812,8 @@
 }
 
 \DeclareExamTemplate{questionbegin}{normal}{
-  \ifbool{exam at resetnumber}{
-    \ifbool{exam at onlyonequestion}{
+  \IfExamBoolTF{resetnumber}{
+    \IfExamBoolTF{onlyonequestion}{
       \renewcommand{\hangtext}{\qquad}
     }{
       \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{question}}.}}\;\,}
@@ -702,7 +865,7 @@
 \let \oldmedskip   = \medskip
 \let \oldbigskip   = \bigskip
 
-\ifbool{exam at random}{
+\IfExamBoolTF{random}{
   \newcommand\rdxm at appto@questions{
     \xappto\allquestions{\expandonce\lastquestion}
   }
@@ -740,7 +903,7 @@
 }
 
 \newcommand{\rdxm at stop@random}{
-  \ifbool{exam at random}{
+  \IfExamBoolT{random}{
     \renewenvironment{question}{\questionreal}{\endquestionreal}
     \renewenvironment{solution}{\solutionreal}{\endsolutionreal}
     \let \newpage   = \oldnewpage
@@ -748,13 +911,13 @@
     \let \smallskip = \oldsmallskip
     \let \medskip   = \oldmedskip
     \let \bigskip   = \oldbigskip
-  }{}
+  }
 }
 
 \def\CommentCutFile{\jobname.cut}
 
 \AtBeginDocument{
-  \ifbool{exam at answer}{}{\excludecomment{solution}}
+  \IfExamBoolF{answer}{\excludecomment{solution}}
 }
 
 %% ---------------------------------------------------------------------------
@@ -848,26 +1011,32 @@
 %% Command for multiple-choice questions: \pickin and \pickout
 %% ---------------------------------------------------------------------------
 
-\newcommand{\answer}[1]{\ifbool{exam at answer}{#1}{\phantom{#1}}}
+\newcommand{\answer}[1]{\IfExamBoolTF{answer}{#1}{\phantom{#1}}}
 
-\newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
-
 \newcommand*{\tick at box}[1]{[\makebox[1.5em]{\color{blue}\answer{#1}}]}
 \newcommand*{\tick at text@t}{$\checkmark$}
 \newcommand*{\tick at text@f}{{\large$\times$}}
 \newcommand*{\tick at text@T}{\sffamily T}
 \newcommand*{\tick at text@F}{\sffamily F}
-\newcommand*{\tickin}[1]{\tick at box{\csname tick at text@#1\endcsname}}
-\newcommand*{\tickout}[1]{\unskip\nobreak\cdotfill\tick at box{\csname tick at text@#1\endcsname}}
 
-\newcommand*{\ulinefill}[1]{\xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt}
+\NewDocumentCommand\tickin{m}{
+  \tick at box{\csname tick at text@#1\endcsname}
+}
+\NewDocumentCommand\tickout{m}{
+  \unskip\nobreak\ExamFillCdot\tick at box{\csname tick at text@#1\endcsname}
+}
+
 \newcommand*{\minwidthbox}[2]{\makebox[{\ifdim#1<\width\width\else#1\fi}]{#2}}
 
-\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}}}
+\NewDocumentCommand\fillout{m}{
+  \allowbreak\hbox{}\nobreak\ExamFillUlineText{\color{blue}\answer{#1}}
+}
+\NewDocumentCommand\fillin{m}{
+  \underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}
+}
 
 \newcommand*\pickoutreal[1]{
-  \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})
+  \unskip\nobreak\ExamFillCdot(\makebox[1.5em]{\color{blue}\answer{#1}})
 }
 \newcommand*\pickinreal[1]{
   \unskip\nobreak
@@ -889,7 +1058,7 @@
 \newcommand\rdxm at shuffle@abcd[1]{\csuse{rdxm at shuffle@\@rdxm at choice@random @#1}}
 
 \newcommand*\pickout[1]{
-  \ifbool{exam at random}{
+  \IfExamBoolTF{random}{
     \exam at set@seed
     \pgfmathrandominteger\@rdxm at choice@random{1}{3}
     %\@rdxm at choice@random
@@ -900,10 +1069,10 @@
 }
 \newcommand*\pickoutfixed[1]{
   \pickoutreal{#1}
-  \boolfalse{exam at random}
+  \SetExamBoolFalse{random}
 }
 \newcommand*\pickin[1]{
-  \ifbool{exam at random}{
+  \IfExamBoolTF{random}{
     \exam at set@seed
     \pgfmathrandominteger\@rdxm at choice@random{1}{3}
     %\@rdxm at choice@random
@@ -914,7 +1083,7 @@
 }
 \newcommand*\pickinfixed[1]{
   \pickinreal{#1}
-  \boolfalse{exam at random}
+  \SetExamBoolFalse{random}
 }
 
 %% ---------------------------------------------------------------------------
@@ -1003,7 +1172,7 @@
   \fi
 }
 
-\ifbool{exam at random}{
+\IfExamBoolT{random}{
   \csdef{rdxm at swap@items at 1}#1#2#3#4{\item#3\item#4\item#1\item#2}
   \csdef{rdxm at swap@items at 2}#1#2#3#4{\item#2\item#1\item#4\item#3}
   \csdef{rdxm at swap@items at 3}#1#2#3#4{\item#4\item#3\item#2\item#1}
@@ -1010,10 +1179,10 @@
   \long\def\rdxm at swap@items#1\item#2\item#3\item#4\item#5\@rdxm at stop@mark{
     #1\csuse{rdxm at swap@items@\@rdxm at choice@random}{#2}{#3}{#4}{#5}
   }
-}{}
+}
 
 \NewDocumentEnvironment{abcd}{+b}{
-  \ifbool{exam at random}{
+  \IfExamBoolTF{random}{
     \begin{abcdreal}\rdxm at swap@items#1\@rdxm at stop@mark\end{abcdreal}
   }{
     \begin{abcdreal}#1\end{abcdreal}
@@ -1020,7 +1189,7 @@
   }
 }{}
 \NewDocumentEnvironment{abcd*}{+b}{
-  \ifbool{exam at random}{
+  \IfExamBoolTF{random}{
     \begin{abcd*real}\rdxm at swap@items#1\@rdxm at stop@mark\end{abcd*real}
   }{
     \begin{abcd*real}#1\end{abcd*real}
@@ -1041,7 +1210,7 @@
 %% ---------------------------------------------------------------------------
 
 \AtBeginDocument{
-  \ifbool{exam at freealign}{\RequirePackage{freealign}}{}
+  \IfExamBoolT{freealign}{\RequirePackage{freealign}}
 }
 
 %% ---------------------------------------------------------------------------
@@ -1075,7 +1244,7 @@
 %% ---------------------------------------------------------------------------
 
 \AtBeginDocument{
-  \ifbool{exam at medmath}{\RequirePackage{medmath}}{}
+  \IfExamBoolT{medmath}{\RequirePackage{medmath}}
 }
 
 %% ---------------------------------------------------------------------------
@@ -1089,27 +1258,6 @@
   \setlength{\belowdisplayshortskip}{2pt}
 }
 
-\setlength\arraycolsep{4pt}
-
-\newrobustcmd\rdxm at 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\rdxm at moremath@limits{
   \AtBeginDocument{
     \let\rdxm at saved@lim=\lim    \def\lim{\rdxm at saved@lim\limits}
@@ -1245,8 +1393,7 @@
   \def\T{\mathrm{T}\kern-.5pt}
 }
 
-\ifbool{exam at moremath}{
-  \rdxm at moremath@diagbox
+\IfExamBoolT{moremath}{
   \rdxm at moremath@limits
   \rdxm at moremath@differential
   \rdxm at moremath@widebar
@@ -1254,7 +1401,7 @@
   \rdxm at moremath@widefrac
   \rdxm at moremath@whitearrow
   \rdxm at moremath@miscellaneous
-}{}
+}
 
 %% ---------------------------------------------------------------------------
 %% Load local user config file
@@ -1266,6 +1413,8 @@
 %% Support for Chinese Language
 %% ---------------------------------------------------------------------------
 
+\IfExamLanguageEqT{chinese}{\SetExamBoolTrue{ctex}}
+
 \newrobustcmd\rdxm at chinese@ctex{
   %% 四号    小四号    五号      小五号
   %% 14bp    12bp      10.5bp    9bp
@@ -1272,17 +1421,9 @@
   %% 实际上,在旧版本 ctex 中只能用 cs4size 和 c5size 选项
   %% 而新版本 ctex 中,可以利用 zihao 选项指定各种中文字号
   \PassOptionsToPackage{CJKnumber}{xeCJK}
-  \RequirePackage[cs4size,UTF8,noindent,heading]{ctex}
-  \ifbool{exam at plain}{\pagestyle{plain}}{\pagestyle{fancy}}
+  \RequirePackage[cs4size,UTF8,noindent]{ctex}
   %% 在旧版本 xeCJK 中,必须用 CJKnumber 选项载入 CJKnumb 包,后面才载入会报错
   %% 但在新版本 xeCJK 中 CJKnumber 选项已经被废弃,需要在后面自行载入它
-  %% 在 xeCJK 中已经禁止载入 CJK,但是在新版本 ctex 宏包中却失效了
-  %% 我们假装 CJK 已经载入,再载入 CJKnumb,避免出现 \CJKglue 重复定义的问题
-  %% 注意用 PDFLaTeX 编译时需要用到 CJK,所以只在未定义时才作修改
-  \ifdefined\CJKglue
-    \@namedef{ver at CJK.sty}{}
-    %\@namedef{opt at CJK.sty}{}
-  \fi
   \RequirePackage{CJKnumb}
   %% 新版本 xeCJK 已经废弃并禁用 CJKfntef,改用 xeCJKfntef 取代,我们需要载入后者
   %% 注意要保证能在较旧的 TeX 系统中编译,我们只能用 \ifXeTeX 而不能用 \ifxetex
@@ -1299,7 +1440,7 @@
     \xeCJKsetcharclass{"2460}{"24FF}{1} % 带圈数字字母,括号数字字母,带点数字等
   }{}
 }
-\ifbool{exam at ctex}{\rdxm at chinese@ctex}{}
+\IfExamBoolT{ctex}{\rdxm at chinese@ctex}
 
 \newrobustcmd\rdxm at chinese@sourcehan{
   \setCJKmainfont[BoldFont=Source~Han~Sans~SC]{Source~Han~Serif~SC}
@@ -1309,11 +1450,11 @@
   %\setCJKsansfont{思源黑体}
 }
 \AtBeginDocument{
-  \ifbool{exam at sourcehan}{
+  \IfExamBoolT{sourcehan}{
     \ifbool{XeTeX}{\rdxm at chinese@sourcehan}{
       \ifbool{LuaTeX}{\rdxm at chinese@sourcehan}{}
     }
-  }{}
+  }
 }
 
 %% 这里不能用 \ifbool,因为涉及到 catcode 的改变
@@ -1348,7 +1489,7 @@
   ,question-Question    = 题
   ,solution-Solution    = 解
 }
-\ifbool{exam at ctex}{\SelectExamTranslation{chinese}}{}
+\IfExamBoolT{ctex}{\SelectExamTranslation{chinese}}
 
 %% ---------------------------------------------------------------------------
 %% Stop ignoring spaces in the code



More information about the tex-live-commits mailing list.