% censor.sty
\def\censorversionnumber{4.0}
\ProvidesPackage{censor}
[2021/12/23 \censorversionnumber
 Provides capability for redaction of sensitive information]

%
% This work may be distributed and/or modified under the 
% conditions of the LaTeX Project Public License, either version 1.3 
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX 
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Steven B. Segletes.

% VERSION:
% 1.00 - Initial release
% 2.00 - Added \blackout
% 2.10 - Allowed \blackout to cross paragraph boundaries with use of
%        \bpar. Stopped censoring periods, in order to preserve
%        end-of-sentence spacing, which differs from inter-word spacing.
% 3.00 - \censorbox introduced to handle figures, tables, etc.
% 3.10 - Made \blackout work with \par in argument.  Introduced 
%        \xblackout
% 3.20 - Specify depth/height of censor rule.  Introduced \def\censordot{}
% 3.21 - Fixed bug regarding \xblackout rules remaining after a
%        \StopCensoring
% 3.22 - changed `\if to \ifx in definition of \bl@t, to handle macros like \%
% 4.0  - Recast \blackout and \xblackout in terms of tokcycle environments
%      - Introduced \blackoutenv...\endblackoutenv and 
%        \xblackoutenv...\endxblackoutenv
\usepackage{pbox}

\newlength\censorruledepth
\newlength\censorruleheight

\censorruledepth=-0.3ex% -0.3ex DEFAULT
\censorruleheight=2.1ex%  2.1ex DEFAULT
\def\censordot{\censor{.}}% versus \def\censordot{ }%

\newcommand\censorrule[1]{\protect\rule[\censorruledepth]{#1}{\censorruleheight}}

\newcommand\censor{\@ifstar{\@cenlen}{\@cenword}}
  \newcommand\@cenlen[1]{\censorrule{#1 ex}}
  \newcommand\@cenword[1]{\censorrule{\widthofpbox{#1}}}

\newcommand\un@censor{\@ifstar{\un@cenlen}{\un@cenword}}
  \newcommand\un@cenlen[1]{\protect\underline{\hspace{#1 ex}}}
  \newcommand\un@cenword[1]{#1}

\newcommand\StopCensoring{%
           \let\censor\un@censor%
           \let\censorbox\un@censorbox%
           \renewcommand\censpace{ }%
}
\newcommand\RestartCensoring{%
           \renewcommand\censor{\@ifstar{\@cenlen}{\@cenword}}%
           \renewcommand\censorbox{\@ifstar{\censor@dim}{\censor@box}}%
           \let\censpace\sv@censpace%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%

\usepackage{tokcycle}[2021/03/10]


\def\@dump#1{\addcytoks[1]{\expandafter\censor\expandafter{#1}}\def#1{}}
\def\@append#1#2{\tc@defx#1{#1#2}}

\def\spacelap{0.6ex}
\def\censpace{\rlap{\censorrule{\spacelap}} \llap{\censorrule{\spacelap}}}
\let\sv@censpace\censpace

\long\def\blackout#1{\blackoutenv#1\endblackoutenv}
\long\def\xblackout#1{\xblackoutenv#1\endxblackoutenv}

\newif\ifexpandarg

\xtokcycleenvironment\xblackoutenv
  {\ifx.##1\@dump\censored@word\addcytoks[1]{\censordot}\else
    \@append\censored@word{##1}%
    \tcpeek\@next\ifx\@next\@tcEscapeptr\@dump\censored@word\fi\fi}
  {\tctestifcon\ifexpandarg{\expandafter\processtoks\expandafter{\expanded{##1}}}%
    {\processtoks{##1}}\@dump\censored@word\expandargfalse}
  {\@dump\censored@word\tctestifx{~##1}{\@append\censored@word{##1}}%
    {\tctestifx{\expanded##1}{\expandargtrue}{\addcytoks{##1}}}}
  {\@dump\censored@word\addcytoks{\censpace}}
  {\def\censored@word{}}
  {\@dump\censored@word}
\xtokcycleenvironment\blackoutenv
  {\ifx.##1\@dump\censored@word\addcytoks[1]{\censordot}\else
    \@append\censored@word{##1}%
    \tcpeek\@next\ifx\@next\@tcEscapeptr\@dump\censored@word\fi\fi}
  {\tctestifcon\ifexpandarg{\expandafter\processtoks\expandafter{\expanded{##1}}}%
    {\processtoks{##1}}\@dump\censored@word\expandargfalse}
  {\@dump\censored@word\tctestifx{~##1}{\@append\censored@word{##1}}%
    {\tctestifx{\expanded##1}{\expandargtrue}{\addcytoks{##1}}}}
  {\@dump\censored@word\addcytoks{##1}}
  {\def\censored@word{}}
  {\@dump\censored@word}



%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand\censorbox{\@ifstar{\censor@dim}{\censor@box}}
  \newcommand\censor@dim[4][]{{#1%
                      \rule[-#4\baselineskip]{#2ex}{#3\baselineskip}}}
  \newcommand\censor@box[2][]{#1\setbox0\hbox{#2}%
                      \rule[-\the\dp0]{\the\wd0}{\the\ht0+\the\dp0}}

\newcommand\un@censorbox{\@ifstar{\un@censor@dim}{\un@censor@box}}
  \newcommand\un@censor@dim[4][]{{#1%
                      \fbox{\rule[-#4\baselineskip]{0ex}{#3\baselineskip}
                      \rule{#2ex}{0ex}}}}
  \newcommand\un@censor@box[2][]{#1#2}

% NOTE: A \protect\censorbox{} MAY BE REQUIRED INSIDE SOME ENVIRONMENTS
\endinput


