%% License: GPL
%% Author: Tobias N"ahring (www.tn-home.de)
%% Date (YY-MM-DD): 04-07-05
%% License: GPL
%% Date (YY-MM-DD): 04-07-09
%% Author: Tobias N"ahring
%% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% The standard header:

\def\fileversion{03}
\def\filedate{2003/02/05}
\message{ v\fileversion, \filedate}

\csname PSTlinestyLoaded\endcsname
\let\PSTlinestyLoaded\endinput

\ifx\PSTricksLoaded\endinput\else
 \def\next{\input pstricks.tex }
 \expandafter\next
\fi

%% Another way of \makeatletter
\edef\TheAtCode{\the\catcode`\@}\catcode`\@=11
%% End of the standard header.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% We need this:
\expandafter\if\csname gobble\endcsname\relax\def\gobble#1{}\fi
%%
%% \newcommand is not native TeX. Therefore the following definition.
%%%%%%%%%%%%
%% \defopt defines a macro with one optional argument.
%% Syntax:
%%   \defopt\MyNewMacro{DefaultValue}[#1]#2{StuffToBeAssignedToMyNewMacro}
%% where \myNewMacro, DefaultValue, and StuffToBeAssignedToMyNewMacro
%% have the obvious meaning. Instead of #2 up to #9 arguments can be
%% specified.
\def\defopt#1#2{%
  \def\defopt@tmp##1{%
    \expandafter\def\csname##1\endcsname{%
      \def\defopt@tmp{\futurelet\defopt@arg}%
      \expandafter\defopt@tmp\csname##1@opt\endcsname%
    }%
    \expandafter\def\csname##1@opt\endcsname{%
      \if\defopt@arg[%]
        \def\next{\csname##1@@opt\endcsname}%
      \else%
        \def\next{\csname##1@@opt\endcsname[#2]}%
      \fi\next}%
    }%
  \edef\defopt@arg{\expandafter\gobble\string#1}
  \expandafter\defopt@tmp\expandafter{\defopt@arg}%
  \expandafter\def\csname\expandafter\gobble\string#1@@opt\endcsname%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Now some auxiliary stuff, special to bcurve:

%% The postscript part of pst-bezier:
\pstheader{pst-bezier.pro}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A list of TeX-code fragments is generated when parsing \bcurve.
%% The list is managed with the help of these two counters:
\newcount\bcurve@codeCntrEnd
\newcount\bcurve@codeCntr
%% These counters should never be set globally.
%% Also the code fragments should never be set globally.
%% The list entries are numberated (therefore the entries can be
%% accessed via \csname only).
%% E. g. for the third entry you have the following items:
%% \csname bcurve@code3l\endcsname (the left control point)
%% \csname bcurve@code3r\endcsname (the right control point)
%% \csname bcurve@code3\endcsname (the interpolated point)
%% \csname bcurve@code3sl\endcsname (the left scaling factor)
%% \csname bcurve@code3sr\endcsname (the right scaling factor)
%% \csname bcurve@code3addon\endcsname (additional code that is run at
%% first)
%% 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Auxiliary macros for dealing
%% with the list TeX-code fragments
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Syntax:
%%  \bcurve@def[offset]{item}{TeXcode}
%% Where offset is some number (default:0),
%% and item is one of {l,r,sl,sr,addon}.
%% TeXcode will be assigned to the item of the list entry at
%% \bcurve@codeCntrEnd + offset.
\defopt\bcurve@def{0}[#1]#2{
  \bcurve@codeCntr\bcurve@codeCntrEnd
  \advance\bcurve@codeCntr by #1
  \expandafter\def\csname bcurve@code\the\bcurve@codeCntr#2\endcsname}

%% Essentially the same as \bcurve@def, but
%% the list item will only be set if it is undefined.
\defopt\bcurve@defIfVoid{0}[#1]#2{
  \bcurve@codeCntr\bcurve@codeCntrEnd
  \let\next\relax
  \advance\bcurve@codeCntr by #1
  \expandafter\ifx\csname %
        bcurve@code\the\bcurve@codeCntr#2\endcsname\relax%
  \def\next{\expandafter\def\csname %
        bcurve@code\the\bcurve@codeCntr#2\endcsname}%
  \fi\next}

%% Essentially the same as \bcurve@def (just \def replaced by \let):
\defopt\bcurve@let{0}[#1]#2{
  \bcurve@codeCntr\bcurve@codeCntrEnd
  \advance\bcurve@codeCntr by #1
  \expandafter\let\csname bcurve@code\the\bcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \bcurve@letvar[offset]{item}\MyVarToBeSet
%% sets \MyVarToBeSet to the value of the list entry.
%% See the definition of \bcurve@def for a description
%% of the list entry.
\defopt\bcurve@letvar{0}[#1]#2#3{
  \bcurve@codeCntr\bcurve@codeCntrEnd
  \advance\bcurve@codeCntr by #1
  \def#3{\noexpand#3}%
  \expandafter\let\expandafter#3\csname bcurve@code\the\bcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \bcurve@ifx[offset]{item}\MyVarToBeCompared
%% That is essentially an \ifx with the list item compared to
%% \MyVarToBeCompared.
\defopt\bcurve@ifx{0}[#1]#2{
  \bcurve@codeCntr\bcurve@codeCntrEnd
  \advance\bcurve@codeCntr by #1
  \expandafter\ifx\csname bcurve@code\the\bcurve@codeCntr#2\endcsname}

%% Syntax:
%%  \bcurve@get{item}
%% This expands to the macro corresponding to `item' from the
%% list entry at \bcurve@codeCntr.
\def\bcurve@get#1{\csname bcurve@code\the\bcurve@codeCntr#1\endcsname}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Auxiliary macros:
%%%%%%%%%%%%%%%%%%%%%
%% Multiple branching
%% Syntax:
%%   \bcurve@switch\ExpandingToKey{KeyI,\MacroI,KeyII,\MacroII,...and so on...}
%% If \ExpandingToKey expands to one of the keys KeyI, \KeyII, ...
%% the corresponding \MacroI, \MacroII, ..., resp. is called.
%% The key value \relax is special. Its corresponding \Macro is the
%% default action which is taken if none of the Keys matches.
\def\bcurve@switch#1#2{%
\def\next##1,##2,##3|{%
\ifx#1##1\relax\def\next####1|{\let\next##2}\fi%
\ifx##1\relax\def\next####1|{\let\next##2}\fi%
\next##3|%
}%
\next#2,\relax,\relax,|\next}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% The user interface to bcurve:
%% Usage: See description in pst-bezier-doc.tex.
%% The default value \relax for the optional argument indicates that
%% there are no optional arguments.
\defopt\bcurve\relax[#1](#2){%
  \bgroup% Makes optional pstricks-settings local to this \bcurve call.
  \ifx#1\relax\else%
    \psset{#1}%
  \fi%
  \def\bcurve@code{%
  \moveto(#2)%
    \code{
      <<
      /Splines [%] begin of the array of splines
      [%] begin of the first dummy spline (just the start point)
      /n /n /n /n } \coor(#2) \code{%
      /n /n %[
      ] % end of the first dummy spline
    }% end of \code
  }%
  %% Initialise the list of postscript code fragments:
  \bcurve@codeCntrEnd0%
  \bcurve@pointSetDefaults%% Init first spline.
  \bcurve@def{l}{\coor(#2)}%% Default left control point of the first spline.
  \bcurve@next%% Now, get the next arguments...
}

%% The following macros declare
%% the pstricks option bcurveTension
%% and set it to its default value.
\def\psset@bcurveTension#1{%
  \def\psk@bcurveTension{#1}%
}
\psset@bcurveTension{0.25}

%% Points of a spline that are not set yet
%% to a certain value or action
%% get the following value:
\def\bcurve@ptNotDef{\code{ /n /n }}

%% A newly allocated spline gets the following
%% defaults:
\def\bcurve@pointSetDefaults{%
  \bcurve@defIfVoid{l}{\bcurve@ptNotDef}%
  \bcurve@defIfVoid{r}{\bcurve@ptNotDef}%
  \bcurve@defIfVoid{sl}{\code{ \psk@bcurveTension\space}}%
  \bcurve@defIfVoid{sr}{\code{ \psk@bcurveTension\space}}%
  \bcurve@defIfVoid{addon}{}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Now, there comes a series of commands.
%% Depending on the next optional modifier
%% in the argument list of \bcurve one of
%% these is called. If there follows a
%% point (x,y) without modifier \bcurve@nextPoint
%% is called. If there follows a token that
%% does not make sense to \bcurve \bcurve@end
%% is called.

%% the modifier l
\def\bcurve@lPoint#1(#2){%
  \bcurve@def{l}{\coor(#2)}%
  \bcurve@next}

%% the modifier r
\def\bcurve@rPoint#1(#2){%
  \bcurve@def{r}{\coor(#2)}%
  \bcurve@next}

%% the modifier L
\def\bcurve@LPoint#1(#2){%
  \bcurve@def{l}{\coor(#2)}%
  \bcurve@def[-1]{r}{\code{ /s /s }}%
  \bcurve@next}

%% the modifier T
\def\bcurve@Tension#1#2{%
\bcurve@def{addon}{\psset@bcurveTension{#2}}%
\bcurve@next}

%% The t modifier has some sub-modifiers
%% These are recognised by this macro and the
%% corresponding action is taken.
\def\bcurve@tension#1{\futurelet\bcurve@tmp\bcurve@@tension}
%%
\def\bcurve@@tension{%
\bcurve@switch\bcurve@tmp{%
l,\bcurve@ltension,%
r,\bcurve@rtension,%
s,\bcurve@stension,%
\relax,\bcurve@@@tension%
}}

%% the modifier t without further sub-modifiers
\def\bcurve@@@tension#1{%
\bcurve@def{sr}{\code{ #1 }}%
\bcurve@def{sl}{\code{ #1 }}%
\bcurve@next}

%% the modifier ts
\def\bcurve@stension#1#2{% symmetric
\bcurve@def[-1]{sr}{\code{ #2 }}%
\bcurve@def{sl}{\code{ #2 }}%
\bcurve@next}

%% the modifier tl
\def\bcurve@ltension#1#2{% left control point
\bcurve@def{sl}{\code{ #2 }}%
\bcurve@next}

%% the modifier tr
\def\bcurve@rtension#1#2{% right control point
\bcurve@def{sr}{\code{ #2 }}%
\bcurve@next}

%% This macro is called if the next token is
%% no modifier but a point (x,y)
\def\bcurve@nextPoint(#1){%
  \bcurve@def{}{\coor(#1)}%
  \advance\bcurve@codeCntrEnd by 1
  \bcurve@pointSetDefaults%
  \bcurve@next}

%% If the next token does not make sense to \bcurve
%% the curve is finished.
\def\bcurve@end{
  %% Do we need to set the last control point to its default?
  \def\tmp{\bcurve@ptNotDef}%
  \bcurve@ifx[-1]{r}\tmp%
    \bcurve@letvar[-1]{}\tmp% \tmp is set to the end point
    \bcurve@let[-1]{r}\tmp% last control point is set to \tmp
  \fi%
  %% pscustom deactivates showpoints: reverse this:
  \let\if@bcurve@showpoints\ifshowpoints%
  \pscustom{%
    %% Following, the TeX-code fragments in \bcurve@code...
    %% are executed. These compose the postscript spline array.
    \bcurve@code%
    \bcurve@codeCntr0
    \loop%
    \code{[ %]
    }%
    \bcurve@get{addon}% additional code
    \bcurve@get{l}% left control point
    \bcurve@get{r}% right control point
    \bcurve@get{}% interpolation point
    \bcurve@get{sl}% left scaling factor
    \bcurve@get{sr}% right scaling factor
    \code{ %[
      ] }% end of the spline.
    \advance\bcurve@codeCntr by 1
    \ifnum\bcurve@codeCntr<\bcurve@codeCntrEnd%
    \repeat%
    \code{%[
      ] % end of the spline array
      /K 1
      >> pstBCurve
          }%
%%%%%%
\if@bcurve@showpoints%
\pst@OpenShowPoints %% works fine, only the dashed lines are missing:
\code{ \tx@BezierShowPoints }%
\fi%
%%%%%%
  }%
  \egroup%
}

%% The following macro reads the next
%% argument from the \bcurve argument list
%% recognises optional modifiers and branches to
%% the corresponding macro.
\def\bcurve@next{\futurelet\bcurve@tmp\bcurve@@next}
\def\bcurve@@next{%
  \bcurve@switch\bcurve@tmp{%
(,\bcurve@nextPoint,%)
l,\bcurve@lPoint,%
r,\bcurve@rPoint,%
L,\bcurve@LPoint,%
t,\bcurve@tension,%
T,\bcurve@Tension,%
\relax,\bcurve@end}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% End of the story:-)
\catcode`\@=\TheAtCode\relax
\endinput
%% local variables:
%% TeX-master: "test-bezier"
%% end:
