% File: alterqcm.sty
% Copyright (c) 2009-2026 Alain Matthes
% Copyright (c) 2019 Alain Matthes, Apostolos Syropoulos, and Anastasios Dimou
% SPDX-License-Identifier: LPPL-1.3c
% Maintainer: Alain Matthes
% Changes: see CHANGELOG.md
%<------------------------->
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{alterqcm}[2026/10/27 v5.00c Multiple choice questionnaires]
\RequirePackage{pgfkeys}
\RequirePackage{calc}% not used by the package itself; kept because users
                     % write \linewidth-1cm etc. inside their questions
\RequirePackage{array}
\RequirePackage{multirow}
\RequirePackage{pifont}
%<------------------------->
%                Languages
%<------------------------->
% \aq@deflang{name}{code}{questions}{answers}{continued}{true}{false}%
%            {text for pre}{text for pre with VF}
\newcount\aqlocall@ng % kept for compatibility
\def\aq@deflang#1#2#3#4#5#6#7#8#9{%
  \@namedef{aq@L@#1@num}{#2}%
  \@namedef{aq@L@#1@quest}{#3}%
  \@namedef{aq@L@#1@rep}{#4}%
  \@namedef{aq@L@#1@foot}{#5}%
  \@namedef{aq@L@#1@true}{#6}%
  \@namedef{aq@L@#1@false}{#7}%
  \@namedef{aq@L@#1@pre}{#8}%
  \@namedef{aq@L@#1@preVF}{#9}}

\aq@deflang{french}{0}{Questions}{Réponses}{Suite sur la page suivante\ldots}
  {\textbf{V}}{\textbf{F}}
  {Pour chacune des questions ci-dessous, une seule des réponses proposées
   est exacte. Vous devez cocher la réponse exacte sans justification.
   Une bonne réponse rapporte \textbf{\cmdAQ@global@bonus\ point}.
   Une mauvaise réponse enlève \textbf{\cmdAQ@global@malus\ point}.
   L'absence de réponse ne rapporte ni n'enlève aucun point.
   Si le total des points est négatif, la note globale attribuée
   à l'exercice est \textbf{0}.}
  {Pour chacune des affirmations ci-dessous, cocher la case V
   (l'affirmation est vraie) ou la case F (l'affirmation est fausse) sur
   l'ANNEXE, à rendre avec la copie. Les réponses ne seront pas justifiées.
   Une bonne réponse rapporte \textbf{\cmdAQ@global@bonus\ point}.
   Une mauvaise réponse enlève \textbf{\cmdAQ@global@malus\ point}.
   L'absence de réponse ne rapporte ni n'enlève aucun point.
   Si le total des points est négatif, la note globale attribuée
   à l'exercice est \textbf{0}.}

\aq@deflang{english}{1}{Questions}{Answers}{Continued on the next page\ldots}
  {\textbf{T}}{\textbf{F}}
  {For each of the questions below, only one of the proposed answers is
   true. You must choose the right answer without justification.}
  {For each of the statements below, check the \textbf{T} box (the
   statement is true) or the \textbf{F} box (the statement is false).}

\aq@deflang{german}{2}{Fragen}{Antworten}{Fortsetzung nächste Seite\ldots}
  {\textbf{R}}{\textbf{F}}
  {Bei jeder der unterstehenden Fragen ist nur eine der vorgeschlagenen
   Antworten richtig. Kreuzen Sie die richtige Antwort ohne Begründung an.}
  {Bei jeder der unterstehenden Aussagen kreuzen Sie \textbf{R} (für die
   richtige Aussage) oder \textbf{F} (für die falsche Aussage) an.}

\aq@deflang{greek}{3}{Ερωτήσεις}{Απαντήσεις}{Συνεχίζεται στην επόμενη σελίδα\ldots}
  {\textbf{Σ}}{\textbf{Λ}}
  {Από τις επόμενες προτάσεις επιλέξετε αυτήν, που θεωρείτε σωστή.}
  {Να επιλέξετε \textbf{Σ}(ωστό), αν θεωρείτε την πρόταση που δίνεται
   παρακάτω σωστή, ή \textbf{Λ}(άθος) αν την θεωρείτε λανθασμένη.}

\aq@deflang{russian}{4}{Вопросы}{Ответы}{Продолжение на следующей странице\ldots}
  {\textbf{П}}{\textbf{Ф}}
  {На каждый из приведенных ниже вопросов верным является только один из
   предложенных ответов. Проверьте правильный ответ без обоснования.}
  {Для каждого из приведенных ниже утверждений проверьте П (для правильного
   утверждения) и Ф (для неверного утверждения).}

\aq@deflang{italian}{5}{Domande}{Risposte}{Continua alla pagina successiva\ldots}
  {\textbf{V}}{\textbf{F}}
  {Per ciascuna delle domande che seguono, solo una delle risposte proposte
   è vera. È necessario scegliere la risposta giusta senza alcuna
   giustificazione.}
  {Per ciascuna delle seguenti affermazioni, selezionare la casella
   \textbf{V} (l'affermazione è vera) o la casella \textbf{F}
   (l'affermazione è falsa).}

\aq@deflang{chinese}{6}{问题}{答案}{请翻页\ldots}
  {\textbf{正}}{\textbf{误}}
  {对于以下提出的各个问题，仅有一个答案是正确的，请选择你认为正确的答案（不需要提供理由）。}
  {对于以下各项陈述，根据陈述内容的正误选择相应的选项（正确的选择“正”，错误的选择“误”）。}

% unknown: the user defines \aqlabelforquest, \aqlabelforrep, \aqfoottext,
% \aqtextfortrue, \aqtextforfalse, \aqpretxt and \aqpretxtVF.
% Titles and footer are left untouched by language=unknown.
\def\aqpretxt{}
\def\aqpretxtVF{}
\def\aqtextfortrue{\textbf{V}}
\def\aqtextforfalse{\textbf{F}}
\@namedef{aq@L@unknown@num}{7}
\@namedef{aq@L@unknown@true}{\aqtextfortrue}
\@namedef{aq@L@unknown@false}{\aqtextforfalse}
\@namedef{aq@L@unknown@pre}{\aqpretxt}
\@namedef{aq@L@unknown@preVF}{\aqpretxtVF}

\def\aq@copy#1#2#3{%
  \ifcsname aq@L@#1@#2\endcsname
    \expandafter\let\expandafter#3\csname aq@L@#1@#2\endcsname
  \fi}
\def\aq@setlang#1{%
  \ifcsname aq@L@#1@num\endcsname
    \aqlocall@ng=\csname aq@L@#1@num\endcsname\relax
    \aq@copy{#1}{quest}\aqlabelforquest
    \aq@copy{#1}{rep}\aqlabelforrep
    \aq@copy{#1}{foot}\aqfoottext
    \aq@copy{#1}{true}\aq@truetext
    \aq@copy{#1}{false}\aq@falsetext
    \aq@copy{#1}{pre}\aq@pre
    \aq@copy{#1}{preVF}\aq@preVF
    \def\cmdAQ@global@tone{\aqlabelforquest}%
    \def\cmdAQ@global@ttwo{\aqlabelforrep}%
  \else
    \PackageError{alterqcm}{Unknown language `#1'}%
      {Available: french, english, german, greek, russian,
       italian, chinese, unknown.}%
  \fi}
%<------------------------->
%                Package options
%<------------------------->
\def\aq@langopt{french}
\@for\aq@tmpa:=french,english,german,greek,russian,italian,chinese\do{%
  \edef\aq@tmpb{\noexpand\DeclareOption{\aq@tmpa}%
    {\noexpand\def\noexpand\aq@langopt{\aq@tmpa}}}%
  \aq@tmpb}
\DeclareOption{unknown}{%
  \def\aq@langopt{unknown}%
  \def\aqlabelforquest{unknown}%
  \def\aqlabelforrep{unknown}%
  \def\aqfoottext{unknown\ldots}}
\ProcessOptions\relax
%<------------------------->
%                Random numbers
%<------------------------->
% \aq@unif{n} expands to an integer in 0..n-1
\ifdefined\pdfuniformdeviate
  \def\aq@unif#1{\pdfuniformdeviate\numexpr#1\relax}
  \def\aq@setseed#1{\pdfsetrandomseed\numexpr#1\relax}
\else\ifdefined\uniformdeviate
  \def\aq@unif#1{\uniformdeviate\numexpr#1\relax}
  \def\aq@setseed#1{\setrandomseed\numexpr#1\relax}
\else
  \def\aq@unif#1{\directlua{tex.sprint(math.random(\number\numexpr#1\relax)-1)}}
  \def\aq@setseed#1{\directlua{math.randomseed(\number\numexpr#1\relax)}}
\fi\fi
%<------------------------->
%                Registers
%<------------------------->
\newcount\aq@i
\newcount\aq@j
\newbox\aq@tempbox
\newdimen\aq@hauteurquest
\newdimen\aq@hauteurprop
\newdimen\aq@wdquest
\newdimen\aq@wdprop
\newdimen\aq@dimtmpa
\newdimen\aq@dimtmpb
\newdimen\aq@dimtmp
\newdimen\aq@lq     % width of the question column
\newdimen\aq@wdrep  % width of the answer column
\newdimen\aq@room   % room left in a cell (transparent mode)
\newtoks\aq@tdml@a
\newtoks\aq@tdml@b
\newcounter{AQ@numquestion}
\newcounter{AQ@numprop}
\newcounter{aq@numb}
\newcounter{aq@identCol}
%<------------------------->
%                Keys
%<------------------------->
\def\aq@storekeys#1#2{% family, list of keys
  \@for\aq@tmpa:=#2\do{%
    \edef\aq@tmpb{\noexpand\pgfkeys{/aq/#1/\aq@tmpa/.store in=%
      \expandafter\noexpand\csname cmdAQ@#1@\aq@tmpa\endcsname}}%
    \aq@tmpb}}
\def\aq@ifkeys#1#2{% family, list of keys
  \@for\aq@tmpa:=#2\do{%
    \expandafter\newif\csname ifAQ@#1@\aq@tmpa\endcsname
    \edef\aq@tmpb{\noexpand\pgfkeys{%
      /aq/#1/\aq@tmpa/.is if=AQ@#1@\aq@tmpa,
      /aq/#1/\aq@tmpa/.default=true}}%
    \aq@tmpb}}

\aq@storekeys{global}{lq,pq,points,symb,corsymb,bonus,malus,numstyle,%
  propstyle,size,tone,ttwo,numbreak,afterpreskip}
\aq@ifkeys{global}{transparent,VF,sep,pre,title,long,num,numprop,%
  nosquare,correction,alea}
\pgfkeys{/aq/global/.cd,
  language/.code = \aq@setlang{#1},
  seed/.code     = \aq@setseed{#1},
}
\aq@storekeys{local}{pq,br}
\aq@storekeys{ann}{propstyle}
\aq@ifkeys{ann}{VF}

\aq@setlang{\aq@langopt}
\pgfkeys{/aq/global/.cd,
  lq           = 100mm,
  pq           = 0pt,
  points       = {},
  sep          = false,
  pre          = false,
  bonus        = {0,5},
  malus        = {0,25},
  VF           = false,
  long         = false,
  symb         = $\square$,
  corsymb      = $\blacksquare$,
  afterpreskip = \medskip,
  num          = true,
  transparent  = false,
  nosquare     = false,
  correction   = false,
  numstyle     = \arabic,
  propstyle    = \alph,
  numprop      = false,
  size         = {},
  title        = true,
  numbreak     = 0,
  alea         = false,
}
\newcommand\AQset[1]{\pgfkeys{/aq/global/.cd,#1}}
\def\aq@setlocal#1{\pgfkeys{/aq/local/.cd,br=5,pq=\cmdAQ@global@pq,#1}}
\def\aq@uselocal{\expandafter\aq@setlocal\expandafter{\aq@localopts}}
%<------------------------->
%                Symbols and tools
%<------------------------->
\newcommand*{\altersquare}{%
  \mbox{\vbox{\hrule\hbox to 6pt{\vrule height 5.2pt \hfil\vrule}\hrule}}}
\newcommand*{\alterblacksquare}{\mbox{\vrule width 6pt height 6pt depth 0pt}}
\AtBeginDocument{%
  \@ifundefined{square}{\let\square\altersquare}{}%
  \@ifundefined{blacksquare}{\let\blacksquare\alterblacksquare}{}}
\newcommand*{\dingsquare}{\ding{114}}
\newcommand*{\dingchecksquare}{%
  \mbox{\ding{114}\hspace{-.7em}\raisebox{.2ex}[1ex]{\ding{51}}}}
\newcommand*{\aq@style@title}{\textbf}
\newcommand*{\aq@style@numquest}{\textbf}
\newcommand*{\aq@style@numrep}{\textbf}
\newcommand\aqheightadvance{4pt}% U. Fischer tex.stackexchange
\newcommand\aqdepthadvance{3pt}
\newcommand*{\AQms}{\aq@ms}
\def\aq@ms(#1,#2){\vrule height #1pt depth #2pt width 0pt}
\newcommand\AQpoints[1]{%
  \marginpar{\begin{tabular}{|c|}\hline\textbf{#1}\\\hline\\\hline\end{tabular}}}
\providecommand\points{\AQpoints}% old name, kept if free (exam defines it)
%<------------------------->
%                Table parts
%<------------------------->
\newcommand{\aq@title}{%
  \hline
   \hfil{\aq@style@title{\cmdAQ@global@tone}}\hfil
 & \hfil{\aq@style@title{\cmdAQ@global@ttwo}}\hfil\\ \hline
 \ifAQ@global@long \endfirsthead
  \hline
   \hfil{\aq@style@title{\cmdAQ@global@tone}}\hfil
 & \hfil{\aq@style@title{\cmdAQ@global@ttwo}}\hfil\\ \hline
  \endhead
  & \raisebox{-1em}\hfill{\emph{\aqfoottext}} \\ \hline
  \endfoot
  \endlastfoot\fi}

\newcommand{\AQmessage}[1]{%
  \multicolumn{2}{|l|}{%
  \begin{minipage}{\dimexpr\textwidth-2\tabcolsep-2\arrayrulewidth\relax}%
  #1
  \end{minipage}}\\ \hline}
%<------------------------->
% proposals are stored in \aq@arg@1, \aq@arg@2, ... (global)
\def\aq@argcs#1{\csname aq@arg@\number#1\endcsname}
\def\aq@storeprops#1{%
  \setcounter{aq@numb}{0}%
  \@for\aq@item:=#1\do{%
    \stepcounter{aq@numb}%
    \global\expandafter\let\csname aq@arg@\number\value{aq@numb}\endcsname
      \aq@item}}
% Fisher-Yates shuffle
\def\aq@shuffle{%
  \aq@i=\value{aq@numb}\relax
  \loop\ifnum\aq@i>\@ne
    \aq@j=\numexpr\aq@unif{\aq@i}+1\relax
    \edef\aq@csi{aq@arg@\the\aq@i}%
    \edef\aq@csj{aq@arg@\the\aq@j}%
    \expandafter\let\expandafter\aq@tmpa\csname\aq@csi\endcsname
    \global\expandafter\let\csname\aq@csi\expandafter\endcsname
      \csname\aq@csj\endcsname
    \global\expandafter\let\csname\aq@csj\endcsname\aq@tmpa
    \advance\aq@i\m@ne
  \repeat}
% height of a proposal -> \aq@dimtmpa
\newcommand{\aq@hauteurbox}[1]{%
  \setbox\aq@tempbox=\vbox{\hsize\aq@wdrep\parbox[t]{\aq@wdrep}{\cmdAQ@global@symb\quad\mbox{#1}}}%
  \aq@dimtmpa\ht\aq@tempbox
  \advance\aq@dimtmpa\dp\aq@tempbox}
% balances the heights of the question and of the proposals
\newcommand{\aq@adjust}[1]{%
  \setbox\aq@tempbox=\vbox{%
    \parbox[t]{\aq@lq}{\aq@style@numquest{\number\value{AQ@numquestion}.}%
    \hspace{3pt}#1}}%
  \aq@wdquest\wd\aq@tempbox
  \aq@hauteurquest\ht\aq@tempbox
  \advance\aq@hauteurquest\dp\aq@tempbox
  \aq@hauteurprop\z@
  \aq@i\z@
  \loop\ifnum\aq@i<\value{aq@numb}%
    \advance\aq@i\@ne
    \expandafter\aq@hauteurbox\expandafter{\aq@argcs\aq@i}%
    \advance\aq@hauteurprop\aq@dimtmpa
  \repeat
  \ifdim\aq@hauteurquest<\aq@hauteurprop
    \global\aq@dimtmp\z@
    \aq@dimtmpa\ht\aq@tempbox
    \aq@dimtmpb\dp\aq@tempbox
    \advance\aq@dimtmpa 3pt
    \advance\aq@dimtmpb 2pt
    \vrule height\aq@dimtmpa depth\aq@dimtmpb width\z@
  \else
    \advance\aq@hauteurquest-\aq@hauteurprop
    \divide\aq@hauteurquest\value{aq@numb}%
    \divide\aq@hauteurquest\tw@
    \global\aq@dimtmp\aq@hauteurquest
  \fi}
%<------------------------->
% one proposal: #1 text, #2 position
\newcommand{\aq@prop}[2]{%
  \setbox\aq@tempbox=\hbox{#1}% natural width (transparent mode)
  \aq@wdprop\wd\aq@tempbox
  \setbox\aq@tempbox=\vbox{#1}%
  \aq@dimtmpa\ht\aq@tempbox
  \advance\aq@dimtmpa\aqheightadvance
  \advance\aq@dimtmpa\aq@dimtmp
  \aq@dimtmpb\dp\aq@tempbox
  \advance\aq@dimtmpb\aqdepthadvance
  \advance\aq@dimtmpb\aq@dimtmp
  \ifAQ@global@VF\hfil\fi
  \ifAQ@global@transparent
    \def\cmdAQ@global@corsymb{$\bigcirc$}%
    \def\cmdAQ@global@symb{}%
  \fi
  \ifAQ@global@numprop
    \stepcounter{AQ@numprop}%
    {\aq@style@numrep{(\cmdAQ@global@propstyle{AQ@numprop})}}%
  \else
    \ifAQ@global@nosquare\else
      \let\aq@symb\cmdAQ@global@symb
      \ifAQ@global@correction
        \@for\aq@good:=\cmdAQ@local@br\do{%
          \ifnum\aq@good=#2\relax\let\aq@symb\cmdAQ@global@corsymb\fi}%
      \fi
      \aq@symb\hspace*{6pt}%
    \fi
  \fi
  \ifAQ@global@transparent
    % invisible rule, no wider than the room left in the cell
    \setbox\aq@tempbox=\hbox{\cmdAQ@global@corsymb\hspace*{6pt}}%
    \aq@room=\dimexpr\linewidth-\wd\aq@tempbox\relax
    \ifdim\aq@wdprop>\aq@room \aq@wdprop=\aq@room\fi
    \vrule height\z@ depth\z@ width\aq@wdprop
  \else
    \ignorespaces#1%
  \fi
  \vrule height\aq@dimtmpa depth\aq@dimtmpb width\z@
  \ifAQ@global@VF\hfil\fi}
%<------------------------->
% builds the rows of the proposals in \aq@rows
\def\aq@buildrows{%
  \def\aq@rows{}%
  \aq@i\z@
  \loop\ifnum\aq@i<\value{aq@numb}%
    \advance\aq@i\@ne
    \edef\aq@rows{\unexpanded\expandafter{\aq@rows}%
      \noexpand&\noexpand\aq@uselocal
      \noexpand\aq@prop{\expandafter\noexpand\aq@argcs\aq@i}{\the\aq@i}\noexpand\\%
      \ifnum\aq@i<\value{aq@numb}%
        \noexpand\ifAQ@global@sep\noexpand\cline{2-2}\noexpand\fi
      \else
        \noexpand\hline
      \fi}%
  \repeat}
% #1 = number of rows spanned by the question
\def\aq@question#1#2{%
  \ifAQ@global@alea\ifAQ@global@VF\else\aq@shuffle\fi\fi
  \aq@adjust{#2}%
  \aq@buildrows
  \multirow{#1}{\aq@lq}[\cmdAQ@local@pq]{%
    \ifAQ@global@num
      \aq@style@numquest{\cmdAQ@global@numstyle{AQ@numquestion}.}\hspace{3pt}%
    \fi
    \ifAQ@global@transparent
      \hrule height\z@ depth\z@ width\aq@wdquest
    \else
      #2%
    \fi
    \vss}%
  \aq@rows}
\def\aq@startquestion#1{%
  \gdef\aq@localopts{#1}%
  \aq@setlocal{#1}%
  \stepcounter{AQ@numquestion}%
  \setcounter{AQ@numprop}{0}}

\newcommand{\AQquestion}[3][]{%
  \aq@startquestion{#1}%
  \aq@storeprops{#3}%
  \aq@question{1}{#2}}

\newcommand{\aq@questionVF}[2][]{%
  \aq@startquestion{#1}%
  \global\expandafter\let\csname aq@arg@1\endcsname\aq@truetext
  \global\expandafter\let\csname aq@arg@2\endcsname\aq@falsetext
  \setcounter{aq@numb}{2}%
  \aq@question{3}{#2}}
%<------------------------->
%                Environment
%<------------------------->
\newenvironment{alterqcm}[1][]{%
  \pgfkeys{/aq/global/.cd,#1}%
  \setlength\aq@lq{\cmdAQ@global@lq}%
  \aq@wdrep=\dimexpr\textwidth-4\tabcolsep-3\arrayrulewidth-\aq@lq\relax
  \ifx\@empty\cmdAQ@global@points\else\AQpoints{\cmdAQ@global@points}\fi
  \setcounter{AQ@numquestion}{\cmdAQ@global@numbreak}%
  \ifAQ@global@VF\let\AQquestion\aq@questionVF\let\aq@pre\aq@preVF\fi
  \ifAQ@global@pre\aq@pre\par\cmdAQ@global@afterpreskip\fi
  \noindent % the table is as wide as \textwidth
  \ifAQ@global@long
    \ifdefined\longtable\else
      \PackageError{alterqcm}{Option `long' needs \string\usepackage{longtable}}%
        {Add \string\usepackage{longtable} to the preamble.
         The table is set with tabular instead.}%
      \AQ@global@longfalse
    \fi
  \fi
  \ifAQ@global@long
    \setlength\LTleft{0pt}%
    \setlength\LTright\fill
    \setlength{\LTpre}{\intextsep}%
    \setlength{\LTpost}{\intextsep}%
    \begin{longtable}[l]{%
      @{}|>{\cmdAQ@global@size}p{\aq@lq}!{\extracolsep{\fill}}%
      |>{\cmdAQ@global@size}p{\aq@wdrep}|@{}}%
  \else
    \begin{tabular}{%
      @{}|>{\cmdAQ@global@size}p{\aq@lq}%
      |>{\cmdAQ@global@size}p{\aq@wdrep}|@{}}%
  \fi
  \ifAQ@global@title\aq@title\else\hline\fi}
 {\ifAQ@global@long\end{longtable}\else\end{tabular}\fi}
%<------------------------->
% #1 path, #2 prefix, #3 list of numbers -- code by J.-C. Charpentier
\newcommand\InputQuestionList[3]{%
  \aq@tdml@a={}%
  \aq@tdml@b={}%
  \ifx\relax#3\relax\else
    \aq@tdml#3,\@nil,\expandafter\aq@tdml@clean\the\aq@tdml@a\@nil
  \fi
  \expandafter\gdef\expandafter\aq@lastval\expandafter{\the\aq@tdml@b}%
  \aq@inputall{#1}{#2}{\the\aq@tdml@a}%
  \aq@inputlast{#1}{#2}{\aq@lastval}}
\long\def\aq@tdml#1,{%
  \ifx\@nil#1\relax
  \else
    \expandafter\aq@addtotoks\the\aq@tdml@b,\to\aq@tdml@a
    \aq@tdml@b={#1}%
    \expandafter\aq@tdml
  \fi}
\long\def\aq@addtotoks#1\to#2{#2=\expandafter{\the#2#1}}
\long\def\aq@tdml@clean,#1\@nil{%
  \ifx\relax#1\relax
    \aq@tdml@a{}%
  \else
    \aq@tdml@@clean#1\@nil
  \fi}
\long\def\aq@tdml@@clean#1,\@nil{\aq@tdml@a{#1}}
\newcommand\aq@inputall[3]{\@for\aq@nb:=#3\do{\input #1#2\aq@nb}}
\newcommand\aq@inputlast[3]{\input#1#2#3}
%<------------------------->
%                Answer sheet
%<------------------------->
% expandable helpers, used inside \edef
\def\aq@annlabel#1{\setcounter{aq@identCol}{#1}\cmdAQ@ann@propstyle{aq@identCol}}
\def\aq@annhead#1#2{% from #1 to #2
  \ifnum#1>#2 \else
    \noexpand&\noexpand\aq@annlabel{#1}%
    \expandafter\aq@annhead\expandafter{\the\numexpr#1+1\relax}{#2}%
  \fi}
\def\aq@annempty#1{%
  \ifnum#1>\z@
    \noexpand&$\noexpand\ $\expandafter\aq@annempty\expandafter{\the\numexpr#1-1\relax}%
  \fi}
\def\aq@annrows#1#2#3{% from #1 to #2, #3 columns
  \ifnum#1>#2 \else
    #1\aq@annempty{#3}\noexpand\tabularnewline\noexpand\hline
    \expandafter\aq@annrows\expandafter{\the\numexpr#1+1\relax}{#2}{#3}%
  \fi}
\newcommand*{\AQannexe}[4][]{%
  \pgfkeys{/aq/ann/.cd,propstyle=\arabic,VF=false,#1}%
  \ifAQ@ann@VF
    \def\aq@tmpa{N&\aq@truetext&\aq@falsetext}%
  \else
    \edef\aq@tmpa{N\aq@annhead{1}{#4}}%
  \fi
  \edef\aq@tmpb{\aq@annrows{#2}{#3}{#4}}%
  \begin{tabular}{*{\number\numexpr#4+1\relax}{|>{\hfill}c}|}\hline
  \aq@tmpa\tabularnewline\hline
  \aq@tmpb
  \end{tabular}}
\endinput
