% censor.sty
\ProvidesPackage{censor}
[2013/02/19 v3.00
 Provides capability for redaction of sensitive information]

%% Copyright 2009, 2012, 2013 Steven B. Segletes
%
% 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.

% Packege: CENSOR
% CHOOSE MODE OF OPERATION:
% 1) IF .tex FILE IS CREATED IN PRIVATE (SECURE) ENVIRONMENT:
%  a) To produce censored document, censor individual words with
%     \censor{word}
%  b) Censor text blocks with \blackout{...}, subject to limitations.
%  c) To produce uncensored document, place \StopCensoring in preamble 
%  d) To produced a mixed document with some redaction, but elsewhere
%     turned off, place \StopCensoring and/or \RestartCensoring in
%     various document locations as needed.
%
% DISCLAIMER: Don't \censor whitespace (i.e., phrases), or justifications
% could get fouled up.  If space-laden phrase needs repeated censoring,
% I suggest typesetting according to the following example:
% \def\CodeName{\blackout{Little Bo Peep}}
% In the text, refer to {\CodeName} as often as needed.
%
% 2) IF .tex FILE IS INITIALLY CREATED IN PUBLIC (UNSECURE) ENVIRONMENT:
%  a) To produce censored document, define (in the document preamble)
%     placeholders for all censored phrases, like:
%     \def\ProjectName{\censor*{7}}
%     In document, refer to {\ProjectName} as needed.  The "7" refers
%     to the approximate width (in ex's) of the censored word.
%  b) Use of \StopCensoring in preamble will merely turn censored
%     black rectangles into underlined blank spaces, since uncensored
%     word is not known to the public source (.tex) document.
%  c) To produce uncensored document, the source code must be moved
%     to a private (secure) working environment.  At that point, the
%     uncensored document may be created merely by editing the document
%     preamble and redefining the censored placeholders, so that
%     \def\ProjectName{\censor*{7}} becomes \def\ProjectName{Liberty},
%     for example.  Note that line justification could be affected, since
%     censored placeholders are not exactly the same width as the
%     actual word, in Mode 2 operation.
%  d) To produced (in the private/secure environment) a mixed document
%     with some redaction, but elsewhere turned off, place \StopCensoring
%     and/or \RestartCensoring in various document locations as needed.
%
% DISCLAIMER: Don't \censor whitespace (i.e., phrases), or justifications
% could get fouled up.  I suggest typesetting multi-word phrases according
% to the following example:
% \def\CodeName{\censor*{6} \censor*{2} \censor*{4}}
% In the text, refer to {\CodeName} as often as needed.
%
% NOTE: For both modes of operation, placeholders are placed in curly
% braces, so that surrounding white space and/or punctuation is properly
% handled.

% 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.

\usepackage{pbox}
\usepackage{ifnextok}

\newcommand\censor{\@ifstar{\@cenlen}{\@cenword}}
  \newcommand\@cenlen[1]{\protect\rule[-.3ex]{#1 ex}{2.1ex}}
  \newcommand\@cenword[1]{%
              \protect\rule[-.3ex]{\widthofpbox{#1}}{2.1ex}}

\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%
}
\newcommand\RestartCensoring{%
           \renewcommand\censor{\@ifstar{\@cenlen}{\@cenword}}%
           \renewcommand\censorbox{\@ifstar{\censor@dim}{\censor@box}}%
}

\def\stringend{$}
\def\blackout#1{\censor@Block#1\stringend}
\def\censor@Block{\IfNextToken\stringend{\@gobble}%
  {\IfNextToken\@sptoken{ \bl@t{\censor@Block}}%
  {\bl@t{\censor@Block}}}}

% V2.00 DEFINITION:
% \def\bl@t#1#2{\censor{#2}#1}

% V2.10 DEFINITION:
\def\bl@t#1#2{\if\bpar#2\par\else\if.#2#2\else\censor{#2}\fi\fi#1}
\def\bpar{_}

% ALTERNATE DEFINITION IF ABOVE PROVES PROBLEMATIC
%\def\bl@t#1#2{\if.#2#2\else\censor{#2}\fi#1} % JUST PERIODS, NO \bpar

\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

