patching \ setcounter e \ addotocounter não funcionam bem com calc

Oct 10 2020

para algumas necessidades muito específicas de reledac, preciso obter o valor do contador de página cada vez que ele é alterado, seja via settocounter, seja com addotcounter.

Então fiz algo assim (é um exemplo muito simplificado e, na realidade, não edito diretamente o contador).

\documentclass{article}
\usepackage{etoolbox}
\usepackage{xstring}
%\usepackage{calc}
\makeatletter
\newcount\this@c@page
\newcommand{\set@this@c@page}{\global\this@c@page=\value{page}}
\apptocmd{\setcounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%
\apptocmd{\addtocounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%
\begin{document}
s
\newpage
\the\this@c@page
\end{document}

Todos funcionam bem, exceto se eu usar o calcpacote. Nesse caso, this@c@pageainda é igual a 0. Parece que a redefinição da macro com esse pacote muda algo para o momento em que podemos obter o valor do contador, mas não entendo por quê.

Algum truque?

Respostas

2 Werner Oct 10 2020 at 02:31

O contador de páginas é incrementado com o \stepcounterque também é atualizado por calc. Aqui está a definição de \stepcounterantes de carregar calc(conforme contido no kernel latex.ltx):

\def\stepcounter#1{%
  \addtocounter{#1}\@ne
  \begingroup
    \let\@elt\@stpelt
    \csname cl@#1\endcsname
  \endgroup}

Observe como \stepcounterusa \addtocounter, que você atualizou e, portanto, funciona conforme o esperado. Aqui está a nova definição de \stepcounter(redefinido por calc):

\def\stepcounter#1{\@ifundefined {c@#1}%
  {\@nocounterr {#1}}%
  {\global\advance\csname c@#1\endcsname \@ne
  \begingroup
    \let\@elt\@stpelt \csname cl@#1\endcsname
  \endgroup}}%

Com calc, \stepcounternão usa \addtocounter, portanto, nenhuma atualização para o pagecontador ou a forma como você o está capturando.

Para corrigir isso, você terá que atualizar \stepcounterda mesma maneira que fez para \setcountere \addtocounter:

\apptocmd{\stepcounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%

calcmenciona que a atualização para \setcounterevitar ter que passar por "todo o calcprocesso" (via \addtocounter).