%       proof.sty       (Proof Figure Macros)
%
%       version 1.0
%       October 13, 1990
%       Copyright (C) 1990 Makoto Tatsuta (tatsuta@riec.tohoku.ac.jp)
%
% This program is free software; you can redistribute it or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either versions 1, or (at your option)
% any later version.
%
% This program is distributed in the hope that it will be useful
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
%       Usage:
%               In \documentstyle, specify an optional style `proof', say,
%                       \documentstyle[proof]{article}.
%
%       The following macros are available:
%
%       In all the following macros, all the arguments such as
%       <Lowers> and <Uppers> are processed in math mode.
%
%       \infer<Lower><Uppers>
%               draws an inference.
%
%               Use & in <Uppers> to delimit upper formulae.
%               <Uppers> consists more than 0 formulae.
%
%               \infer returns \hbox{ ... } or \vbox{ ... } and
%               sets \@LeftOffset and \@RightOffset globally.
%
%       \infer[<Label>]<Lower><Uppers>
%               draws an inference labeled with <Label>.
%
%       \infer*<Lower><Uppers>
%               draws a many step deduction.
%
%       \infer*[<Label>]<Lower><Uppers>
%               draws a many step deduction labeled with <Label>.
%
%       \deduce<Lower><Uppers>
%               draws an inference without a rule.
%
%       \deduce[<Proof>]<Lower><Uppers>
%               draws a many step deduction with a proof name.
%
%       Example:
%               If you want to write
%                           B C
%                          -----
%                      A     D
%                     ----------
%                         E
%       use
%               \infer{E}{
%                       A
%                       &
%                       \infer{D}{B & C}
%               }
%

%       Style Parameters

\newdimen\inferLineSkip         \inferLineSkip=2pt
\newdimen\inferLabelSkip        \inferLabelSkip=5pt
\def\inferTabSkip{\quad}

%       Variables

\newdimen\@LeftOffset   % global
\newdimen\@RightOffset  % global
\newdimen\@SavedLeftOffset      % safe from users

\newdimen\UpperWidth
\newdimen\LowerWidth
\newdimen\LowerHeight
\newdimen\UpperLeftOffset
\newdimen\UpperRightOffset
\newdimen\UpperCenter
\newdimen\LowerCenter
\newdimen\UpperAdjust
\newdimen\RuleAdjust
\newdimen\LowerAdjust
\newdimen\RuleWidth
\newdimen\HLabelAdjust
\newdimen\VLabelAdjust
\newdimen\WidthAdjust

\newbox\@UpperPart
\newbox\@LowerPart
\newbox\@LabelPart
\newbox\ResultBox

%       Flags

\newif\if@inferRule     % whether \@infer draws a rule.
\newif\if@ReturnLeftOffset      % whether \@infer returns \@LeftOffset.
\newif\if@MathSaved     % whether inner math mode where \infer or
                        % \deduce appears.

%       Special Fonts

\def\DeduceSym{\vtop{\baselineskip4\p@ \lineskiplimit\z@
    \vbox{\hbox{.}\hbox{.}\hbox{.}}\hbox{.}}}

%       Math Save Macros
%
%       \@SaveMath is called in the very begining of toplevel macros
%       which are \infer and \deduce.
%       \@RestoreMath is called in the very last before toplevel macros end.
%       Remark \infer and \deduce ends calling \@infer.

%\def\@SaveMath{\@MathSavedfalse \ifmmode \ifinner
%        \relax $\relax \@MathSavedtrue \fi\fi }
%
%\def\@RestoreMath{\if@MathSaved \relax $\relax\fi }

\def\@SaveMath{\relax}
\def\@RestoreMath{\relax}


%       Macros

\def\@ifEmpty#1#2#3{\def\@tempa{\@empty}\def\@tempb{#1}\relax
        \ifx \@tempa \@tempb #2\else #3\fi }

\def\infer{\@SaveMath \@ifnextchar *{\@inferSteps}{\@inferOneStep}}

\def\@inferOneStep{\@inferRuletrue
        \@ifnextchar [{\@infer}{\@infer[\@empty]}}

\def\@inferSteps*{\@ifnextchar [{\@@inferSteps}{\@@inferSteps[\@empty]}}

\def\@@inferSteps[#1]{\@deduce{#1}[\DeduceSym]}

\def\deduce{\@SaveMath \@ifnextchar [{\@deduce{\@empty}}
        {\@inferRulefalse \@infer[\@empty]}}

%       \@deduce<Proof Label>[<Proof>]<Lower><Uppers>

\def\@deduce#1[#2]#3#4{\@inferRulefalse
        \@infer[\@empty]{#3}{\@SaveMath \@infer[{#1}]{#2}{#4}}}

%       \@infer[<Label>]<Lower><Uppers>
%               If \@inferRuletrue, draws a rule and <Label> is right to
%               a rule.
%               Otherwise, draws no rule and <Label> is right to <Lower>.

\def\@infer[#1]#2#3{\relax
% Get parameters
        \if@ReturnLeftOffset \else \@SavedLeftOffset=\@LeftOffset \fi
        \setbox\@LabelPart=\hbox{$#1$}\relax
        \setbox\@LowerPart=\hbox{$#2$}\relax
%
        \global\@LeftOffset=0pt
        \setbox\@UpperPart=\vbox{\tabskip=0pt \halign{\relax
                \global\@RightOffset=0pt \@ReturnLeftOffsettrue $##$&&
                \inferTabSkip
                \global\@RightOffset=0pt \@ReturnLeftOffsetfalse $##$\cr
                #3\cr}}\relax
%                       Here is a little trick.
%                       \@ReturnLeftOffsettrue(false) influences on \infer or
%                       \deduce placed in ## locally
%                       because of \@SaveMath and \@RestoreMath.
        \UpperLeftOffset=\@LeftOffset
        \UpperRightOffset=\@RightOffset
% Calculate Adjustments
        \LowerWidth=\wd\@LowerPart
        \LowerHeight=\ht\@LowerPart
        \LowerCenter=0.5\LowerWidth
%
        \UpperWidth=\wd\@UpperPart \advance\UpperWidth by -\UpperLeftOffset
        \advance\UpperWidth by -\UpperRightOffset
        \UpperCenter=\UpperLeftOffset
        \advance\UpperCenter by 0.5\UpperWidth
%
        \ifdim \UpperWidth > \LowerWidth
                % \UpperCenter > \LowerCenter
        \UpperAdjust=0pt
        \RuleAdjust=\UpperLeftOffset
        \LowerAdjust=\UpperCenter \advance\LowerAdjust by -\LowerCenter
        \RuleWidth=\UpperWidth
        \global\@LeftOffset=\LowerAdjust
%
        \else   % \UpperWidth <= \LowerWidth
        \ifdim \UpperCenter > \LowerCenter
%
        \UpperAdjust=0pt
        \RuleAdjust=\UpperCenter \advance\RuleAdjust by -\LowerCenter
        \LowerAdjust=\RuleAdjust
        \RuleWidth=\LowerWidth
        \global\@LeftOffset=\LowerAdjust
%
        \else   % \UpperWidth <= \LowerWidth
                % \UpperCenter <= \LowerCenter
%
        \UpperAdjust=\LowerCenter \advance\UpperAdjust by -\UpperCenter
        \RuleAdjust=0pt
        \LowerAdjust=0pt
        \RuleWidth=\LowerWidth
        \global\@LeftOffset=0pt
%
        \fi\fi
% Make a box
        \if@inferRule
%
        \setbox\ResultBox=\vbox{
                \moveright \UpperAdjust \box\@UpperPart
                \nointerlineskip \kern\inferLineSkip
                \moveright \RuleAdjust \vbox{\hrule width\RuleWidth}\relax
                \nointerlineskip \kern\inferLineSkip
                \moveright \LowerAdjust \box\@LowerPart }\relax
%
        \@ifEmpty{#1}{}{\relax
%
        \HLabelAdjust=\wd\ResultBox     \advance\HLabelAdjust by -\RuleAdjust
        \advance\HLabelAdjust by -\RuleWidth
        \WidthAdjust=\HLabelAdjust
        \advance\WidthAdjust by -\inferLabelSkip
        \advance\WidthAdjust by -\wd\@LabelPart
        \ifdim \WidthAdjust < 0pt \WidthAdjust=0pt \fi
%
        \VLabelAdjust=\dp\@LabelPart
        \advance\VLabelAdjust by -\ht\@LabelPart
        \VLabelAdjust=0.5\VLabelAdjust  \advance\VLabelAdjust by \LowerHeight
        \advance\VLabelAdjust by \inferLineSkip
%
        \setbox\ResultBox=\hbox{\box\ResultBox
                \kern -\HLabelAdjust \kern\inferLabelSkip
                \raise\VLabelAdjust \box\@LabelPart \kern\WidthAdjust}\relax
%
        }\relax % end @ifEmpty
%
        \else % \@inferRulefalse
%
        \setbox\ResultBox=\vbox{
                \moveright \UpperAdjust \box\@UpperPart
                \nointerlineskip \kern\inferLineSkip
                \moveright \LowerAdjust \hbox{\unhbox\@LowerPart
                        \@ifEmpty{#1}{}{\relax
                        \kern\inferLabelSkip \unhbox\@LabelPart}}}\relax
        \fi
%
        \global\@RightOffset=\wd\ResultBox
        \global\advance\@RightOffset by -\@LeftOffset
        \global\advance\@RightOffset by -\LowerWidth
        \if@ReturnLeftOffset \else \global\@LeftOffset=\@SavedLeftOffset \fi
%
        \box\ResultBox
        \@RestoreMath
}
