diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-12 23:59:45 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-12 23:59:45 +0000 |
commit | 07c26f83f669b504de20d91fdef8009c43629352 (patch) | |
tree | 753f1bcbaaba3e204c55bc2fdbf68e80e3dda5be /Master/texmf-dist/tex/latex/msc | |
parent | 91686423316d9adbdb83d6ed2e97c61f1e46d335 (diff) |
msc
git-svn-id: svn://tug.org/texlive/trunk@1110 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/msc')
-rw-r--r-- | Master/texmf-dist/tex/latex/msc/msc.sty | 3119 |
1 files changed, 3119 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/msc/msc.sty b/Master/texmf-dist/tex/latex/msc/msc.sty new file mode 100644 index 00000000000..6cf2b0e2ef7 --- /dev/null +++ b/Master/texmf-dist/tex/latex/msc/msc.sty @@ -0,0 +1,3119 @@ +%% MSC Macro Package +%% file msc.sty +%% LaTeX macros to draw message sequence charts +%% +%% +%% Copyright 2002 V. Bos and S. Mauw +% +% This program may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.2 +% 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.2 or later is part of all distributions of LaTeX +% version 1999/12/01 or later. + +% This program consists of the files +% msc.sty +% manual.tex +% manual.ps +% refman.tex +% refman.ps +% biblio.bib +% maintenance.tex +% maintenance.ps +% README +% COPYRIGHT + +% Address: +% Eindhoven University of Technology +% P.O. Box 513 +% 5600 MB Eindhoven +% The Netherlands +% Email: sjouke@win.tue.nl, vbos@abo.fi +% Updates via: http://www.win.tue.nl/~sjouke/mscpackage.html +% and via CTAN directory: macros/latex/contrib/msc/ +% +% RCS version: $Id: msc.sty,v 1.15 2004/03/15 11:58:33 vbos Exp $ +% +\def\mscdate{2004/03/15}% update this whenever this file changes +\def\mscversion{1.14}% update this whenever a new version is ready +\NeedsTeXFormat{LaTeX2e}% +\ProvidesPackage{msc}[\mscdate, v\mscversion] +\typeout{msc version \mscversion. (\mscdate)} +\RequirePackage{color,pstricks,calc,ifthen} +% +% mscunit: the unit of msc lengths +\def\mscunit{cm}% +\def\setmscunit#1{\gdef\mscunit{#1}} +% +% +% +% msc lengths +% First the customizable lengths: + +\newlength{\actionheight}% height of action symbols +\newlength{\actionwidth}% width of action symbol +\newlength{\bottomfootdist}% distance between bottom of foot symbol and frame +\newlength{\msccommentdist}% distance of comment to its instance +\newlength{\conditionheight}% height of condition symbols +\newlength{\conditionoverlap}% overlap of condition symbol +\newlength{\envinstdist}% distance between environments and nearest instance line +\newlength{\firstlevelheight}% height of level just below head symbols +\newlength{\hmscconditionheight}% height of hmsc condition symbol +\newlength{\hmscconditionwidth}% width of hmsc condition symbol +\newlength{\hmscconnectionradius}% radius of hmsc connection symbols +\newlength{\hmscreferenceheight}% height of hmsc reference symbol +\newlength{\hmscreferencewidth}% width of hmsc reference symbol +\newlength{\hmscstartsymbolwidth}% width of hmsc start symbol +\newlength{\inlineoverlap}% overlap of inline symbol +\newlength{\instbarwidth}% default width of vertical instance bars +\newlength{\instdist}% distance between (vertical) instance lines +\newlength{\instfootheight}% height of foot symbols +\newlength{\instheadheight}% height of head symbols +\newlength{\instwidth}% width of header and foot symbols +\newlength{\labeldist}% distance between labels and message lines or head symbol boxes +\newlength{\lastlevelheight}% height of level just above foot symbols +\newlength{\leftnamedist}% distance between left of frame and (top of) msc title +\newlength{\levelheight}% height of a level +\newlength{\lostsymbolradius}% radius of the lost and found symbols +\newlength{\markdist}% distance between mark and its instance +\newlength{\measuredist}% user definable length for horizontal measure distance +\newlength{\measuresymbolwidth}% width of measure symbols +\newlength{\mscdocreferenceheight}% minimal height of mscdoc reference +\newlength{\mscdocreferencewidth}% minimal width of mscdoc reference +\newlength{\referenceoverlap}% overlap of reference symbol +\newlength{\regionbarwidth}% width of region bars +\newlength{\selfmesswidth}% length of horizontal arms of self messages +\newlength{\stopwidth}% width of the stop symbol +\newlength{\timerwidth}% width of the timer symbols +\newlength{\topheaddist}% distance between top of head symbols and frame +\newlength{\topnamedist}% distance between top of frame and (top of) msc title + +% +% Now the internal lengths +\newlength{\tmp@X} +\newlength{\tmp@Y} +\newlength{\tmp@Xa} +\newlength{\tmp@Ya} +\newlength{\tmp@Xb} +\newlength{\tmp@Yb} +\newlength{\tmp@Xc} +\newlength{\tmp@Yc} +\newlength{\tmp@Xd} +\newlength{\tmp@Yd} +\newlength{\msc@currentheight} +\newlength{\msc@currentwidth} +\newlength{\msc@totalwidth} +\newlength{\msc@totalheight} +\newlength{\msc@commentdist}% distance of comment to its instance +% +% +\newcommand{\msc@incrcounter}[1]{\addtocounter{#1}{1}}% +% +% internal box +\newsavebox{\tmp@box} +% +% some internal offsets +\def\msc@leveloffset{0}% +\def\mscscalefactor{1}% +\newcommand{\setmscscale}[1]{\def\mscscalefactor{#1}}% +% +% Command to change the footer color (legal values are black, gray, +% lightgray, and white) +\def\setfootcolor#1{\def\msc@footcolor{#1}} +% +% And some internal counters +\newcounter{mscinstcnt} +\newcounter{tmpcnt} +% +% \messlabelpos defines the position of message labels. +% The default value is "l" (left) other value(s) are "r" (right) +\def\timerpos{l} +% +% \msc@timerpos is the internal variant of \timerpos +% This internal variant is used by the actual drawing commands for self messages +\def\msc@timerpos{l} +% +% \msc@settimerpos sets the internal \mes@timerpos +\def\msc@settimerpos#1{ + \ifthenelse{\not\(\equal{#1}{l} \or \equal{#1}{r}\)}{% + \msc@unknowntimerposerr{#1}}{% else + \def\msc@timerpos{#1}% + }% +} +% +% \dummyinst{#1} (\dummyinst*{#1}) declares a dummy msc-instance and does not +% draws its head symbol nor its instance axis until an instance create/start is +% encountered. The starred version declares a fat instance. +% #1: nickname that can be used in \mess -like commands +% +\def\dummyinst{\@ifstar{\msc@dummyinststar}{\msc@dummyinstnostar}} +\def\msc@dummyinstnostar#1{% + \msc@makedummyinst{\the\instbarwidth}{#1}% +} +\def\msc@dummyinststar#1{% + \msc@makedummyinst{\the\instwidth}{#1}% +} +\def\msc@makedummyinst#1#2{% + \@ifundefined{mscinst#2}{% + \ifthenelse{\value{mscinstcnt}=2}{% Aha: this is the first msc instance, so, add the + \addtolength{\msc@currentwidth}{\envinstdist}% left \envinstdist to \msc@currentwidth + }{%not the first instance , so add the instdist to the \mec@currentwidth + \addtolength{\msc@currentwidth}{\instdist}% + }% and update x-pos of right environment + \setlength{\tmp@X}{\msc@currentwidth+\envinstdist}% + \msc@setinstxpos{envright}{\the\tmp@X}% + % make an instance with empty inside name and empty above name: + \msc@declinst{#2}{\relax}{\relax}{#1}% + % make y-pos undefined, to make sure that no instance line will be drawn + \msc@setinstypos{#2}{undefined}% --added sm + }{% else: nickname #2 already defined! + \msc@nicknamedefinederr{#2}% + }% +} +% +% \declinst[*] declares a new msc-instance and draws its head symbol +% the starred versions makes a fat instance. +% #1: nickname that can be used in \mess +% #2: name of the instance (above instance head symbol) +% #3: name of the instance (inside instance head symbol) +% +% +\def\declinst{\@ifstar{\msc@declinststar}{\msc@declinstnostar}} +% +% Some commands are defined as well (INSTNR is the arabic +% representation of the instance number): +% \instabname#1: `above name' of instance with nickname #1 +% \instinname#1: `inside name' of instance with nickname #1 +% \instnicknameINSTNR: returns the nickname of instance INSTNR +% \instxposINSTNR: returns the x-position of instance with nickname #1 +% \instyposINSTNR: returns the last y-position of instance with nickname #1 +% \instlinestyle#1: the line style (dashed or solid) of instance with nickname #1 +\def\msc@declinstnostar#1#2#3{% user command to declare instances + \msc@dummyinstnostar{#1}% + %\inststart{#1}{#2}{#3}% + % define above name and inside name + \expandafter\def\csname instabname#1\endcsname{#2}% `above name' + \expandafter\def\csname instinname#1\endcsname{#3}% `inside name' + % draw the instance header symbol + \msc@drawinstanceheadsymbol{#1}{\the\topheaddist}% + % redefine the instance's y position + \setlength{\tmp@Y}{\topheaddist+\instheadheight}% + \msc@setinstypos{#1}{\the\tmp@Y}% +} +% +\def\msc@declinststar#1#2#3{% user command to declare instances + \msc@dummyinststar{#1}% + % define above name and inside name + \expandafter\def\csname instabname#1\endcsname{#2}% `above name' + \expandafter\def\csname instinname#1\endcsname{#3}% `inside name' + % draw the instance header symbol + \msc@drawinstanceheadsymbol{#1}{\the\topheaddist}% + % redefine the instance's y position + \setlength{\tmp@Y}{\topheaddist+\instheadheight}% + \msc@setinstypos{#1}{\the\tmp@Y}% +} +% +% \msc@declinst: internal command to declare instances. +% Some commands are defined as well (INSTNR is the arabic +% representation of the instance number): +% \instabnameINSTNR: returns the instance above name of #1 +% \instnicknameINSTNR: returns the nickname of instance #1 +% \instxposINSTNR: returns the x-position of instance with nickname #1 +% \instyposINSTNR: returns the last y-position of instance with nickname #1 +% \instlinestyle#1: the line style (dashed or solid) of instance with nickname #1 +% \instregionstyle#1: the region style (normal, coregion, suspension, or activation) +\def\msc@declinst#1#2#3#4{% internal command to declare instances + \@ifundefined{mscinst#1}{% + \@namedef{mscinst#1}{\relax}% + \expandafter\def\csname instabname#1\endcsname{#2}% `above name' + \expandafter\def\csname instinname#1\endcsname{#3}% `inside name' + \expandafter\def\csname instbarwidth#1\endcsname{#4}% width of the vertical instance bar + % the x position of an instance, \instxpos#1, is stored as a string, not as + % a TeX-length, since that would use up too much of TeX limited number of + % length-registers. + % However, this means we first have to calculate the x-pos, and then + % assign the string representation of the result to \instxpos#1: + \setlength{\tmp@X}{\msc@currentwidth}% + \expandafter\edef\csname instxpos#1\endcsname{\the\tmp@X}% + \ifthenelse{\lengthtest{\instbarwidth < #4}}% + {% + \expandafter\def\csname instisfat#1\endcsname{true}% + \setlength{\tmp@Xa}{#4}% + \addtolength{\tmp@X}{-.5\tmp@Xa}% + \expandafter\edef\csname instlxpos#1\endcsname{\the\tmp@X}% + \addtolength{\tmp@X}{\tmp@Xa}% + \expandafter\edef\csname instrxpos#1\endcsname{\the\tmp@X}% + }% + {% + \expandafter\def\csname instisfat#1\endcsname{false}% + \expandafter\edef\csname instlxpos#1\endcsname{\the\tmp@X}% + \expandafter\edef\csname instrxpos#1\endcsname{\the\tmp@X}% + }% + \expandafter\def\csname instnickname\arabic{mscinstcnt}\endcsname{#1}% + \setlength{\tmp@Y}{\msc@currentheight}% + \expandafter\edef\csname instypos#1\endcsname{\the\tmp@Y}% + \expandafter\def\csname instlinestyle#1\endcsname{solid}% + \expandafter\def\csname instfootcolor#1\endcsname{\msc@footcolor}% + \expandafter\def\csname instregionstyle#1\endcsname{normal}% + \msc@incrcounter{mscinstcnt}% + }{% else, #1 already defined + \msc@nicknamedefinederr{#1}% + }% +} +% +% \msc@instnickname gets the nickname of msc instance with number #1 +% (This macro is used in \msc@drawinstancelevels) +\def\msc@instnickname#1{% + \csname instnickname\arabic{#1}\endcsname% +} +% \msc@instabname gets the above name of instance #1 +\def\msc@instabname#1{% + \csname instabname#1\endcsname% +} +% \msc@instinname gets the inside name of instance #1 +\def\msc@instinname#1{% + \csname instinname#1\endcsname% +} +% +% \msc@instxpos gets the x position (i.e., horizontal position) of the +% msc instance with nickname #1. +\def\msc@instxpos#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\csname instxpos#1\endcsname}% +} +% +% +\def\msc@instlxpos#1{ + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\csname instlxpos#1\endcsname}% +} +% +\def\msc@instrxpos#1{ + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\csname instrxpos#1\endcsname}% +} +% +% \msc@setinstxpos sets the (l/r) x position of instance with nickname #1 to +% the string #2 +\def\msc@setinstxpos#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname instxpos#1\endcsname{#2}% + \expandafter\edef\csname instlxpos#1\endcsname{#2}% + \expandafter\edef\csname instrxpos#1\endcsname{#2}% + }% +} +% +\def\msc@setinstlxpos#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname instlxpos#1\endcsname{#2}% + }% +} +% +\def\msc@setinstrxpos#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname instrxpos#1\endcsname{#2}% + }% +} +% +% \msc@instypos gets the last y position (i.e., vertical position) of the +% msc instance with nickname #1. +\def\msc@instypos#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instypos#1\endcsname}% +} +% +% \msc@setinstypos sets the last y position of instance with nickname #1 to +% the string #2 +\def\msc@setinstypos#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname instypos#1\endcsname{#2}% + }% +} +% +% Change \instlinestyle command of msc instance with nickname #1 into #2 +% #2 should be one of: solid, dashed, or dotted +\def\msc@setinstlinestyle#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \ifthenelse{\not\(\equal{#2}{solid} \or + \equal{#2}{dashed} \or + \equal{#2}{dotted}\)}{% unknown linestyle + \msc@unknownlinestyleerr{#2}}{% + \expandafter\def\csname instlinestyle#1\endcsname{#2}% + }% + }% +} +% +% \msc@instlinestyle returns the linestyle of instance with nickname #1 +\def\msc@instlinestyle#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instlinestyle#1\endcsname}% +} +% +% Change the foot color for instance with nickname #1 into #2 +\def\msc@setinstfootcolor#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\def\csname instfootcolor#1\endcsname{#2}% + }% +} +% +% \msc@instfootcolor returns the color of the footer of instance with nicknam #1 +\def\msc@instfootcolor#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instfootcolor#1\endcsname}% +} +% +% Change \instregionstyle command of msc instance with nickname #1 into #2 +% #2 should be one of: normal, coregion, suspension, or activation +\def\msc@setinstregionstyle#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \ifthenelse{\not\(\equal{#2}{normal} \or + \equal{#2}{coregion} \or + \equal{#2}{suspension} \or + \equal{#2}{activation}\)} + {% unknown region style + \msc@unknownregionstyleerr{#2} + }{% + \expandafter\def\csname instregionstyle#1\endcsname{#2}% + }% + \ifthenelse{\equal{#2}{suspension} \or \equal{#2}{activation}} + {% + \ifthenelse{\equal{\msc@instisfat{#1}}{true}} + {\relax} + {% + \setlength{\tmp@X}{\msc@instxpos{#1}}% + \setlength{\tmp@Xa}{\regionbarwidth}% + \addtolength{\tmp@X}{-.5\tmp@Xa}% + \msc@setinstlxpos{#1}{\the\tmp@X}% + \addtolength{\tmp@X}{\tmp@Xa}% + \msc@setinstrxpos{#1}{\the\tmp@X}% + } + }{% new region style is normal or coregion + \ifthenelse{\equal{\msc@instisfat{#1}}{true}}% + {\relax}% + {\msc@setinstbarwidth{#1}{\instbarwidth}% + \msc@setinstlxpos{#1}{\msc@instxpos{#1}}% + \msc@setinstrxpos{#1}{\msc@instxpos{#1}}% + }% + }% + }% +} +% +% \msc@instregionstyle returns the region style of instance with nickname #1 +\def\msc@instregionstyle#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instregionstyle#1\endcsname}% +} +% +% \msc@instbarwidth returns the width of the bar of instance with nickname #1 +\def\msc@instbarwidth#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instbarwidth#1\endcsname}% +} +% +% \msc@setinstbarwidth sets the width of the bar of instance with nickname #1 +% to the string #2 +\def\msc@setinstbarwidth#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname instbarwidth#1\endcsname{#2}% + \ifthenelse{\lengthtest{\instbarwidth < #2}}% + {\expandafter\def\csname instisfat#1\endcsname{true}}% + {\expandafter\def\csname instisfat#1\endcsname{false}}% + }% +} +% +%\msc@isfateinst returns one of the strings `true' of `false', indicating if +% the instance with nickname #1 is a fat instance. +\def\msc@instisfat#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \csname instisfat#1\endcsname}% +} +% +% +% \changeinstbarwidth changes the instance width of instance with nickname #1 to +% the length #2 +\def\changeinstbarwidth#1#2{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}% + {% else, #1 is defined + \msc@drawinstanceline{#1}% + \setlength{\tmp@X}{\msc@instxpos{#1}}% + \setlength{\tmp@Y}{\msc@currentheight}% + \msc@setinstypos{#1}{\the\tmp@Y}% + \setlength{\tmp@Xb}{#2}% + \ifthenelse{\lengthtest{\tmp@Xb > \instbarwidth}}% + {% + \setlength{\tmp@Xb}{0.5\tmp@Xb}% + \addtolength{\tmp@Xb}{\tmp@X}}% + {% + \setlength{\tmp@Xb}{\tmp@X}}% + \ifthenelse{\equal{true}{\msc@instisfat{#1}}} + {% + \setlength{\tmp@Xa}{\msc@instbarwidth{#1}}% + \setlength{\tmp@Xa}{0.5\tmp@Xa}% + \addtolength{\tmp@Xa}{\tmp@X}% + }{% + \setlength{\tmp@Xa}{\tmp@X}% + }% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + \setlength{\tmp@Xb}{#2}% + \ifthenelse{\lengthtest{\tmp@Xb > \instbarwidth}}% + {% + \setlength{\tmp@Xb}{-0.5\tmp@Xb}% + \addtolength{\tmp@Xb}{\tmp@X}}% + {% + \setlength{\tmp@Xb}{\tmp@X}}% + \ifthenelse{\equal{true}{\msc@instisfat{#1}}} + {% + \setlength{\tmp@Xa}{\msc@instbarwidth{#1}}% + \setlength{\tmp@Xa}{-0.5\tmp@Xa}% + \addtolength{\tmp@Xa}{\tmp@X}% + }{% + \setlength{\tmp@Xa}{\tmp@X}% + }% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + \msc@setinstbarwidth{#1}{#2}% + }% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DUMMY INSTANCES (start and stop) +% +% Start a dummy inst +% +% \inststart{#1}{#2}{#3} +% #1: nickname of stared instance +% #2: name of the instance (above instance head symbol) +% #3: name of the instance (inside instance head symbol) +% +\def\inststart#1#2#3{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + % set the above and inside names + \expandafter\def\csname instabname#1\endcsname{#2}% `above name' + \expandafter\def\csname instinname#1\endcsname{#3}% `inside name' + % draw the instance header symbol + \msc@drawinstanceheadsymbol{#1}{\the\msc@currentheight}% + % redefine the instance's y position + \setlength{\tmp@Y}{\msc@currentheight+\instheadheight}% + \msc@setinstypos{#1}{\the\tmp@Y}% + } +} +% +% \inststop{#1} +% #1: nick name of instance +% +% Draws the footer of #1 at current level. +\def\inststop#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \addtolength{\msc@currentheight}{\lastlevelheight} + \msc@drawinstanceline{#1}% + \setlength{\tmp@Y}{\msc@currentheight}% + \msc@drawinstancefootsymbol{#1}{\the\tmp@Y}% + \addtolength{\msc@currentheight}{-\lastlevelheight} + \msc@setinstypos{#1}{undefined} + } +} +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 +% +% CREATE +% +% \create creates a new msc-instance and draws its head symbol +% #1: text above creation message +% #2: nickname of creating instance +% #3: nickname of created instance +% #4: name of the instance (above instance head symbol) +% #5: name of the instance (inside instance head symbol) +% +% Some commands are defined as well (INSTNR is the arabic +% representation of the instance number): +% \instabname#3: `above name' of instance with nickname #3 +% \instinname#3: `inside name' of instance with nickname #3 +% \instlinestyle#3: the line style (dashed or solid) of instance with nickname #3 +\newcommand{\create}{% + \@ifstar% + {\def\mess@style{mess}\def\mess@linsestyle{dashed}\create@A}{\def\mess@style{mess}\def\mess@linestyle{solid}\create@A}% +}% +\newcommand{\create@A}[1]{% + \def\mess@labeltext{#1}% + \create@B% +} +\newcommand{\create@B}[2][t]{% + \def\mess@labelposition{#1}% + \def\mess@sender{#2}% + \create@C% +} +\newcommand{\create@C}[4][0.5]{% + \def\mess@labelplacement{#1}% + \def\mess@receiver{#2}% + \def\mess@leveloffset{0}% + \def\mess@instanceoffset{0.5\instwidth}% +% + \expandafter\@ifundefined{mscinst\mess@sender}{% + \msc@instundefinederr{\mess@sender}}{% else, \mess@sender is defined + \expandafter\@ifundefined{mscinst\mess@receiver}{% + \msc@instundefinederr{\mess@receiver}}{% else, \mess@receiver is defined + \expandafter\def\csname instabname\mess@receiver\endcsname{#3}% `above name' + \expandafter\def\csname instinname\mess@receiver\endcsname{#4}% `inside name' + % draw the instance header symbol + \setlength{\tmp@X}{\msc@instxpos{\mess@receiver}}% x-center head box + \setlength{\tmp@Y}{\msc@currentheight}% y-center head box + \setlength{\tmp@Xa}{-0.5\instwidth+\tmp@X}% x-upperleft head box + \setlength{\tmp@Ya}{\msc@currentheight-0.5\instheadheight}% + \setlength{\tmp@Xb}{\tmp@Xa+\instwidth}% x-lowerright head box + \setlength{\tmp@Yb}{\tmp@Ya+\instheadheight}% y-lowerright head box + \psframe[dimen=middle](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + \rput[B](\tmp@X,-\tmp@Ya){\raisebox{\labeldist}{\makebox[0pt][c]{#3}}}% + \rput[B](\tmp@X,-\tmp@Y){\raisebox{-.5ex}{\makebox[0pt][c]{#4}}}% + % redefine the instance's y position + \setlength{\tmp@Y}{\msc@currentheight+0.5\instheadheight}% + \msc@setinstypos{\mess@receiver}{\the\tmp@Y}% + % draw creation arrow + \msc@drawarrow% + }% + }% +} +% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% INLINE EXPRESSIONS (inlines) +% +% +% \inlineestart creates an inline expression at the current level +% [#1]: left overlap +% [#2]: right overlap +% #3: nickname of the inline +% #4: text of the inline +% #5: first instance of the inline +% #6: final instance of the inline +\newcommand{\inlinestart}[1][\inlineoverlap]{% + \def\msc@leftoverlap{#1}\msc@inlinecont% +} +\newcommand{\msc@inlinecont}[5][\msc@leftoverlap]{\msc@declinline{\msc@leftoverlap}{#1}{#2}{#3}{#4}{#5}}% +% +% \inlineend draws and ends the inline expression with nickname #1 +% +\newcommand{\inlineend}{% + \@ifstar{\msc@inlineends}{\msc@inlineend}} +% +% \inlineseparator draws a ``separator'' (horizontal dashed line) through +% inline expression with nickname #1 +\newcommand{\inlineseparator}[1]{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \setlength{\tmp@Y}{\msc@currentheight}% + \psline[linestyle=dashed](\msc@inlulx{#1},-\tmp@Y)(\msc@inllrx{#1},-\tmp@Y)% + }% +} +% +% internal commands to implement the inline expressions: +% #1: left overlap +% #2: right overlap +% #3: nickname of the inline +% #4: text of the inline +% #5: first instance of the inline +% #6: final instance of the inline +% +\def\msc@declinline#1#2#3#4#5#6{% + \@ifundefined{mscinl#3}{% + \@ifundefined{mscinst#5}{% #5 is not an instance nickname + \msc@instundefinederr{#5}}{% + \@ifundefined{mscinst#6}{% #6 is not an instance nickname + \msc@instundefinederr{#6}}{% + \ifthenelse{\lengthtest{\msc@instxpos{#5}>\msc@instxpos{#6}}}{% + \msc@inlfirstlasterror{#3}{#5}{#6}}{% + \@namedef{mscinl#3}{\relax}% + \expandafter\def\csname inltext#3\endcsname{\raisebox{\depth}[\totalheight][0pt]{#4}}% + \ifthenelse{\equal{true}{\msc@instisfat{#5}}}% + {% + \setlength{\tmp@X}{\msc@instlxpos{#5}-#1}% + }% + {% + \setlength{\tmp@X}{\msc@instxpos{#5}-#1}% + }% + \expandafter\edef\csname inlulx#3\endcsname{\the\tmp@X}% + \expandafter\edef\csname inluly#3\endcsname{\the\msc@currentheight}% + \ifthenelse{\equal{true}{\msc@instisfat{#6}}}% + {% + \setlength{\tmp@X}{\msc@instrxpos{#6}+#2}% + }% + {% + \setlength{\tmp@X}{\msc@instxpos{#6}+#2}% + }% + \expandafter\edef\csname inllrx#3\endcsname{\the\tmp@X}% + \expandafter\edef\csname inllry#3\endcsname{undefined}% + % two additional instances are defined + \msc@declinst{#3left}{\relax}{\relax}{\the\instbarwidth}% left of inline + \msc@setinstxpos{#3left}{\msc@inlulx{#3}}% + \msc@setinstlxpos{#3left}{\msc@inlulx{#3}}% + \msc@setinstrxpos{#3left}{\msc@inlulx{#3}}% + \msc@setinstypos{#3left}{undefined}% no instance line drawing + \msc@declinst{#3right}{\relax}{\relax}{\the\instbarwidth}% left of inline + \msc@setinstxpos{#3right}{\msc@inllrx{#3}}% + \msc@setinstlxpos{#3right}{\msc@inllrx{#3}}% + \msc@setinstrxpos{#3right}{\msc@inllrx{#3}}% + \msc@setinstypos{#3right}{undefined}% no instance line drawing + }% + }% + }% + }{% nickname #3 already defined + \msc@nicknamedefinederr{#3}% + }% +} +% +% \msc@inlulx gets the upper-left x-position of inline with nickname #1. +\def\msc@inlulx#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \csname inlulx#1\endcsname% + }% +} +% +% \msc@inluly gets the upper-left y-position of inline with nickname #1. +\def\msc@inluly#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \csname inluly#1\endcsname% + }% +} +% +% \msc@inllrx gets the lower-right x-position of inline with nickname #1. +\def\msc@inllrx#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \csname inllrx#1\endcsname% + }% +} +% +% \msc@inllry gets the lower-right y-position of inline with nickname #1. +\def\msc@inllry#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \csname inllry#1\endcsname% + }% +} +% +% \msc@inltext gets the text of inline with nickname #1 +\def\msc@inltext#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \csname inltext#1\endcsname% + }% +} +% +% \msc@inlineend completes the inline with nickname #1 +% (the bottom line is solid) +\def\msc@inlineend#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname inllry#1\endcsname{\the\msc@currentheight}% + \setlength{\tmp@Xa}{\msc@inlulx{#1}}% + \setlength{\tmp@Ya}{\msc@inluly{#1}}% + \setlength{\tmp@Xb}{\msc@inllrx{#1}}% + \setlength{\tmp@Yb}{\msc@inllry{#1}}% +%% Debug info: +% \typeout{(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)}% + \psframe[dimen=middle](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + \settowidth{\tmp@X}{\msc@inltext{#1}}% + \setlength{\tmp@X}{1.1\tmp@X+\labeldist}% + \settoheight{\tmp@Y}{\msc@inltext{#1}}% + \setlength{\tmp@Y}{1.1\tmp@Y+\labeldist}% + \setlength{\tmp@Xb}{\tmp@X+\labeldist}% + \setlength{\tmp@Yb}{\tmp@Y+\labeldist}% + \rput(\tmp@Xa,-\tmp@Ya){% + \rput[tl](\labeldist,-\labeldist){\msc@inltext{#1}}% + \psline(0,-\tmp@Yb)(\tmp@X,-\tmp@Yb)(\tmp@Xb,-\tmp@Y)(\tmp@Xb,0)% + }% + }% +} +% +% \msc@inlineends completes the inline with nickname #1 +% (the bottom line is dashed) +\def\msc@inlineends#1{% + \expandafter\@ifundefined{mscinl#1}{% + \msc@inlundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname inllry#1\endcsname{\the\msc@currentheight}% + \setlength{\tmp@Xa}{\msc@inlulx{#1}}% + \setlength{\tmp@Ya}{\msc@inluly{#1}}% + \setlength{\tmp@Xb}{\msc@inllrx{#1}}% + \setlength{\tmp@Yb}{\msc@inllry{#1}}% +%% Debug info: +% \typeout{(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)}% + % first the solid part of the inline expression: + \psline(\tmp@Xa,-\tmp@Yb)(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + % then the dashed bottom line: + \psline[linestyle=dashed](\tmp@Xa,-\tmp@Yb)(\tmp@Xb,-\tmp@Yb) + \settowidth{\tmp@X}{\msc@inltext{#1}}% + \setlength{\tmp@X}{1.1\tmp@X+\labeldist}% + \settoheight{\tmp@Y}{\msc@inltext{#1}}% + \setlength{\tmp@Y}{1.1\tmp@Y+\labeldist}% + \setlength{\tmp@Xb}{\tmp@X+\labeldist}% + \setlength{\tmp@Yb}{\tmp@Y+\labeldist}% + \rput(\tmp@Xa,-\tmp@Ya){% + \rput[tl](\labeldist,-\labeldist){\msc@inltext{#1}}% + \psline(0,-\tmp@Yb)(\tmp@X,-\tmp@Yb)(\tmp@Xb,-\tmp@Y)(\tmp@Xb,0)% + }% + }% +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% REFERENCES +% +% +% \referencestart creates an msc reference at the current level +% [#1] : left overlap +% [#2] : right overlap +% #3: nickname of the reference +% #4: text of the reference +% #5: first instance of the reference +% #6: final instance of the reference +\newcommand{\referencestart}[1][\referenceoverlap]{% + \def\msc@leftoverlap{#1}\msc@referencecont% +} +\newcommand{\msc@referencecont}[5][\referenceoverlap]{% + \msc@declreference{\msc@leftoverlap}{#1}{#2}{#3}{#4}{#5}% + \setcounter{tmpcnt}{0}% + \msc@reffindfirst{#2}{\msc@drawtorefaux}% +} +% +% \referenceend draws and ends the reference with nickname #1 +\newcommand{\referenceend}[1]{% + \msc@drawreference{#1}% + \setcounter{tmpcnt}{0}% + \setlength{\tmp@Y}{\msc@currentheight}% + \msc@reffindfirst{#1}{\msc@refresetypos{\the\tmp@Y}}% +} +% +% internal commands to implement references: +% #1: left overlap +% #2: right overlap +% #3: nickname of the reference +% #4: text of the reference +% #5: first instance of the reference +% #6: final instance of the reference +% +\def\msc@declreference#1#2#3#4#5#6{% + \@ifundefined{mscref#3}{% + \@ifundefined{mscinst#5}{% #5 is not an instance nickname + \msc@instundefinederr{#5}}{% + \@ifundefined{mscinst#6}{% #6 is not an instance nickname + \msc@instundefinederr{#6}}{% + \ifthenelse{\lengthtest{\msc@instxpos{#5}>\msc@instxpos{#6}}}{% + \msc@reffirstlasterror{#3}{#5}{#6}}{% + \@namedef{mscref#3}{\relax}% + \expandafter\def\csname reftext#3\endcsname{#4}% + \ifthenelse{\equal{true}{\msc@instisfat{#5}}}% + {% + \setlength{\tmp@X}{\msc@instlxpos{#5}-#1}% + }% + {% + \setlength{\tmp@X}{\msc@instxpos{#5}-#1}% + }% + \expandafter\edef\csname refulx#3\endcsname{\the\tmp@X}% + \expandafter\edef\csname refuly#3\endcsname{\the\msc@currentheight}% + \ifthenelse{\equal{true}{\msc@instisfat{#6}}}% + {% + \setlength{\tmp@X}{\msc@instrxpos{#6}+#2}% + }% + {% + \setlength{\tmp@X}{\msc@instxpos{#6}+#2}% + }% + \expandafter\edef\csname reflrx#3\endcsname{\the\tmp@X}% + \expandafter\edef\csname reflry#3\endcsname{undefined}% + \expandafter\def\csname reffirst#3\endcsname{#5}% + \expandafter\def\csname reffinal#3\endcsname{#6}% + % two additional instances are defined + \msc@declinst{#3left}{\relax}{\relax}{\the\instbarwidth}% left of reference + \msc@setinstxpos{#3left}{\msc@refulx{#3}}% + \msc@setinstlxpos{#3left}{\msc@refulx{#3}}% + \msc@setinstrxpos{#3left}{\msc@refulx{#3}}% + \msc@setinstypos{#3left}{undefined}% no instance line drawing + \msc@declinst{#3right}{\relax}{\relax}{\the\instbarwidth}% left of reference + \msc@setinstxpos{#3right}{\msc@reflrx{#3}}% + \msc@setinstlxpos{#3right}{\msc@reflrx{#3}}% + \msc@setinstrxpos{#3right}{\msc@reflrx{#3}}% + \msc@setinstypos{#3right}{undefined}% no instance line drawing + }% + }% + }% + }{% nickname #3 already defined + \msc@nicknamedefinederr{#3}% + }% +} +% +% \msc@refulx gets the upper-left x-position of reference with nickname #1. +\def\msc@refulx#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname refulx#1\endcsname% + }% +} +% +% \msc@refuly gets the upper-left y-position of reference with nickname #1. +\def\msc@refuly#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname refuly#1\endcsname% + }% +} +% +% \msc@reflrx gets the lower-right x-position of reference with nickname #1. +\def\msc@reflrx#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname reflrx#1\endcsname% + }% +} +% +% \msc@reflry gets the lower-right y-position of reference with nickname #1. +\def\msc@reflry#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname reflry#1\endcsname% + }% +} +% +% \msc@reftext gets the text of reference with nickname #1 +\def\msc@reftext#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname reftext#1\endcsname% + }% +} +% +% \msc@reftext gets the nickname of the first instance of the reference with nickname #1 +\def\msc@reffirst#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname reffirst#1\endcsname% + }% +} +% +% \msc@reftext gets the nickname of the final instance of the reference with nickname #1 +\def\msc@reffinal#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \csname reffinal#1\endcsname% + }% +} +% +% \msc@drawreference completes the reference with nickname #1 +\def\msc@drawreference#1{% + \expandafter\@ifundefined{mscref#1}{% + \msc@refundefinederr{#1}}{% else, #1 is defined + \expandafter\edef\csname reflry#1\endcsname{\the\msc@currentheight}% + \setlength{\tmp@Xa}{\msc@refulx{#1}}% + \setlength{\tmp@Ya}{\msc@refuly{#1}}% + \setlength{\tmp@Xb}{\msc@reflrx{#1}}% + \setlength{\tmp@Yb}{\msc@reflry{#1}}% +%% Debug info: +% \typeout{(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)}% + \psframe[dimen=middle,framearc=0.25](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% note: rounded corners + \setlength{\tmp@X}{\tmp@Xb-\tmp@Xa}% + \setlength{\tmp@Y}{\tmp@Yb-\tmp@Ya}% + \rput(\tmp@Xa,-\tmp@Ya){% + \rput[B](.5\tmp@X,-.5\tmp@Y){\raisebox{-.5ex}{\makebox[0pt][c]{\msc@reftext{#1}}}}% + }% + }% +} +% +\def\msc@reffindfirst#1#2{% + \ifthenelse{\value{tmpcnt} < \value{mscinstcnt}}{% +% Debug info: +% \typeout{(drawtoref) checking \msc@instnickname{tmpcnt}}% + \ifthenelse{\equal{\msc@instnickname{tmpcnt}}{\msc@reffirst{#1}}}{% first instance found +% Debug info: +% \typeout{first found: \msc@instnickname{tmpcnt}}% + #2{#1}}{% else, keep on looking + \msc@incrcounter{tmpcnt}% + \msc@reffindfirst{#1}{#2}}}{% done ! all instances checked + }% +} +% +\def\msc@drawtorefaux#1{% + \ifthenelse{\value{tmpcnt} < \value{mscinstcnt}}{% +% Debug info: +% \typeout{(drawtorefaux) checking \msc@instnickname{tmpcnt}}% + \msc@drawinstanceline{\msc@instnickname{tmpcnt}}% + \msc@setinstypos{\msc@instnickname{tmpcnt}}{undefined}% + \ifthenelse{\equal{\msc@instnickname{tmpcnt}}{\msc@reffinal{#1}}}{% final instance found +% Debug info: +% \typeout{final found: \msc@instnickname{tmpcnt}}% + }{% else, non-final + \msc@incrcounter{tmpcnt}% + \msc@drawtorefaux{#1}}% + }{% done ! all instances checked + }% +} +% +\def\msc@refresetypos#1#2{% + \ifthenelse{\value{tmpcnt} < \value{mscinstcnt}}{% +% Debug info: +% \typeout{(drawtorefaux) checking \msc@instnickname{tmpcnt}} + \msc@setinstypos{\msc@instnickname{tmpcnt}}{#1}% + \ifthenelse{\equal{\msc@instnickname{tmpcnt}}{\msc@reffinal{#2}}}{% final instance found +% Debug info: +% \typeout{final found: \msc@instnickname{tmpcnt}}% + }{% else, non-final + \msc@incrcounter{tmpcnt}% + \msc@refresetypos{#1}{#2}}% + }{% done ! all instances checked + }% +} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% CO-REGIONS +% +% \coregionstart starts a coregion on instance #1 (nickname) in the current level. +\def\coregionstart#1{\regionstart{coregion}{#1}} +% \coregionend ends a coregion on instance #1 (nickname) in the current level. +\def\coregionend#1{\regionend{#1}}% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% REGIONS (normal, coregion, suspension, and activation) +% +% +% \regionstart{#1}{#2} +% starts a region +% #1: region style: normal, coregion, suspension, or activation +% #2: nickname: nick name of the instance +\def\regionstart#1#2{% + \expandafter\@ifundefined{mscinst#2}{% + \msc@instundefinederr{#2}}{% else, #2 is defined + \msc@drawinstanceline{#2}% + \msc@setinstregionstyle{#2}{#1}% + \msc@drawregionstart{#2}% + }% +} +% +% \regionend{#1} +% ends the region of instance with nickname #1 +\def\regionend#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \msc@drawinstanceline{#1}% + \msc@drawregionend{#1}% + \msc@setinstregionstyle{#1}{normal}% + }% +} +% +% +\def\msc@drawregionstart#1{% + \setlength{\tmp@Y}{\msc@currentheight}% + \ifthenelse{\equal{\msc@instisfat{#1}}{true}} + {% + \setlength{\tmp@Xa}{\msc@instlxpos{#1}}% + \setlength{\tmp@Xb}{\msc@instrxpos{#1}}% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + } + {% + \setlength{\tmp@Xa}{-.5\regionbarwidth+\msc@instxpos{#1}}% + \setlength{\tmp@Xb}{.5\regionbarwidth+\msc@instxpos{#1}}% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + } + \msc@setinstypos{#1}{\the\tmp@Y}% +} +% +% +\def\msc@drawregionend#1{% + \setlength{\tmp@Y}{\msc@currentheight}% + \ifthenelse{\equal{\msc@instisfat{#1}}{true}} + {% + \setlength{\tmp@Xa}{\msc@instlxpos{#1}}% + \setlength{\tmp@Xb}{\msc@instrxpos{#1}}% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + } + {\setlength{\tmp@Xa}{-.5\regionbarwidth+\msc@instxpos{#1}}% + \setlength{\tmp@Xb}{.5\regionbarwidth+\msc@instxpos{#1}}% + \psline(\tmp@Xa,-\tmp@Y)(\tmp@Xb,-\tmp@Y)% + } + \msc@setinstypos{#1}{\the\tmp@Y}% +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MESSAGE ARROWS +% +% \messarrowscale sets the arrow scale +\def\messarrowscale#1{\psset{arrowscale=#1}} +% +% \msc@setleveloffset sets the internal level offset +\def\msc@setleveloffset#1{% + \def\msc@leveloffset{#1}% +} + +% \mess has one optional argument to define the position of +% the label of a self message. +\newcommand{\mess}{% + \@ifstar% + {\def\mess@style{mess}\def\mess@linestyle{dashed}\mess@A}{\def\mess@style{mess}\def\mess@linestyle{solid}\mess@A}% +}% +% +\newcommand{\mess@A}[2][l]{% + \def\selfmess@position{#1}% + \def\mess@labeltext{#2}% + \mess@B% +}% +\newcommand{\mess@B}[2][\ifx\mess@sender\mess@receiver \selfmess@position\else t\fi]{% + \def\mess@labelposition{#1}% + \def\mess@sender{#2}% + \mess@C% +} +\newcommand{\mess@C}[2][0.5]{% + \def\mess@labelplacement{#1}% + \def\mess@receiver{#2}% + \mess@D% +} +\newcommand{\mess@D}[1][\ifx\mess@sender\mess@receiver 1\else 0\fi]{% + \edef\mess@leveloffset{#1}% + \mess@E% +} +\newcommand{\mess@E}[1][0\mscunit]{% + \edef\mess@instanceoffset{#1}% + \msc@drawarrow% +} +\newcommand{\msc@drawarrow}{% + \expandafter\@ifundefined{mscinst\mess@sender}{% + \msc@instundefinederr{\mess@sender}}{% else, sender is defined + \expandafter\@ifundefined{mscinst\mess@receiver}{% + \msc@instundefinederr{\mess@receiver}}{% else, receiver is defined + \ifx\mess@sender\mess@receiver\msc@drawselfarrow\else\msc@drawnonselfarrow\fi% + }% + }% +} +\newcommand{\msc@drawselfarrow}{% + \ifthenelse{\equal{\selfmess@position}{l} \or% + \equal{\selfmess@position}{r}% + }{% + \ifthenelse{\equal{\selfmess@position}{l}}% + {% + \setlength{\tmp@Xa}{\msc@instlxpos{\mess@sender} - \selfmesswidth}% + \setlength{\tmp@Xb}{\tmp@Xa}% + }{% ELSE + \setlength{\tmp@Xa}{\msc@instrxpos{\mess@sender} + \selfmesswidth}% + \setlength{\tmp@Xb}{\tmp@Xa}% + }% + \setlength{\tmp@Ya}{\msc@currentheight}% + \setlength{\tmp@Yb}{\msc@currentheight + (\levelheight * \mess@leveloffset)}% + \msc@computelabelcoords% + \msc@computelabelspec% + \rput[\msc@labelrefpoint](\tmp@X,-\tmp@Y){\msc@labelbox{\mess@labeltext}}% + \ifthenelse{\equal{\selfmess@position}{l}}% + {% + \setlength{\tmp@Xa}{\msc@instlxpos{\mess@sender}}% + \setlength{\tmp@Xc}{\msc@instlxpos{\mess@sender} - \mess@instanceoffset}% + }{% ELSE + \setlength{\tmp@Xa}{\msc@instrxpos{\mess@sender}}% + \setlength{\tmp@Xc}{\msc@instrxpos{\mess@sender} + \mess@instanceoffset}% + }% + \ifthenelse{\equal{\mess@style}{mess}}% + {% THEN message arrow + \psline[linestyle=\mess@linestyle]{->}% + (\tmp@Xa,-\tmp@Ya)% + (\tmp@Xb,-\tmp@Ya)% + (\tmp@Xb,-\tmp@Yb)% + (\tmp@Xc,-\tmp@Yb)% + }{% ELSE order arrow + \setlength{\tmp@Yd}{.5\tmp@Yb + .5\tmp@Ya}% + \psline[linestyle=\mess@linestyle]{->}% + (\tmp@Xa,-\tmp@Ya)% + (\tmp@Xb,-\tmp@Ya)% + (\tmp@Xb,-\tmp@Yd)% + \psline[linestyle=\mess@linestyle]% + (\tmp@Xb,-\tmp@Yd)% + (\tmp@Xb,-\tmp@Yb)% + (\tmp@Xc,-\tmp@Yb)% + }% + }{% ELSE + \msc@illegalselfmesspositionerr{\selfmess@position}% + }% +} +\newcommand{\msc@drawnonselfarrow}{% + \ifthenelse{\lengthtest{\msc@instxpos{\mess@sender} < \msc@instxpos{\mess@receiver}}}% + {\setlength{\tmp@Xa}{\msc@instrxpos{\mess@sender}}% + \setlength{\tmp@Xb}{\msc@instlxpos{\mess@receiver}}% + \addtolength{\tmp@Xb}{-\mess@instanceoffset}}% + {\setlength{\tmp@Xa}{\msc@instlxpos{\mess@sender}}% + \setlength{\tmp@Xb}{\msc@instrxpos{\mess@receiver}}% + \addtolength{\tmp@Xb}{\mess@instanceoffset}}% + \setlength{\tmp@Ya}{\msc@currentheight}% + \setlength{\tmp@Yb}{\msc@currentheight + (\levelheight * \mess@leveloffset)}% + \msc@computelabelcoords% + \msc@computelabelspec% + \ifthenelse{\equal{\mess@style}{mess}}% + {% THEN message arrow + \psline[linestyle=\mess@linestyle]{->}% + (\tmp@Xa,-\tmp@Ya)% + (\tmp@Xb,-\tmp@Yb)% + }{%ELSE order arrow + \setlength{\tmp@Xd}{.5\tmp@Xb + .5\tmp@Xa}% + \setlength{\tmp@Yd}{.5\tmp@Yb + .5\tmp@Ya}% + \psline[linestyle=\mess@linestyle]{->}% + (\tmp@Xa,-\tmp@Ya)% + (\tmp@Xd,-\tmp@Yd)% + \psline[linestyle=\mess@linestyle]% + (\tmp@Xd,-\tmp@Yd)% + (\tmp@Xb,-\tmp@Yb)% + }% + \rput[\msc@labelrefpoint](\tmp@X,-\tmp@Y){\msc@labelbox{\mess@labeltext}}% +}% + +\newcommand{\msc@computelabelcoords}{% + \ifthenelse{%\equal{t}{t}% + \(\equal{\mess@sender}{\mess@receiver} \and \(\equal{\mess@labelposition}{l} \or% + \equal{\mess@labelposition}{r}\)% + \)% + \or% + \(\not\(\equal{\mess@sender}{\mess@receiver}\) \and \(\equal{\mess@labelposition}{t} \or% + \equal{\mess@labelposition}{b}\)% + \)% + }{% THEN + \ifthenelse{\lengthtest{\tmp@Xa<\tmp@Xb}}% + {% THEN + \ifthenelse{\lengthtest{\tmp@Ya<\tmp@Yb}}% + {% THEN + \setlength{\tmp@X}{\tmp@Xa + (\tmp@Xb - \tmp@Xa)*\real{\mess@labelplacement}}% + \setlength{\tmp@Y}{\tmp@Ya + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}% + }{% ELSE + \setlength{\tmp@X}{\tmp@Xa + (\tmp@Xb - \tmp@Xa)*\real{\mess@labelplacement}}% + \setlength{\tmp@Y}{\tmp@Yb + (\tmp@Ya - \tmp@Yb) + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}% + }% + }{% ELSE + \ifthenelse{\lengthtest{\tmp@Xa>\tmp@Xb}}% + {% THEN + \ifthenelse{\lengthtest{\tmp@Ya<\tmp@Yb}}% + {% THEN + \setlength{\tmp@X}{\tmp@Xb + (\tmp@Xa - \tmp@Xb) + (\tmp@Xb - \tmp@Xa)*\real{\mess@labelplacement}}% + \setlength{\tmp@Y}{\tmp@Ya + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}% + }{% ELSE + \setlength{\tmp@X}{\tmp@Xb + (\tmp@Xa - \tmp@Xb) + (\tmp@Xb - \tmp@Xa)*\real{\mess@labelplacement}}% + \setlength{\tmp@Y}{\tmp@Yb + (\tmp@Ya - \tmp@Yb) + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}% + }% + }{% ELSE \tmpXa = \tmp@Xb (self message) + \setlength{\tmp@X}{\tmp@Xa}% + \ifthenelse{\lengthtest{\tmp@Ya<\tmp@Yb}}% + {% + \setlength{\tmp@Y}{\tmp@Ya + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}% + }{% + \setlength{\tmp@Y}{\tmp@Yb + (\tmp@Ya - \tmp@Yb) + (\tmp@Yb - \tmp@Ya)*\real{\mess@labelplacement}}}% + }% + }% + }{% ELSE + \msc@illegalmesslabelpositionerr{\mess@labelposition}% + } +} + +\newcommand{\msc@computelabelspec}{% + \ifthenelse{\lengthtest{\tmp@Xa < \tmp@Xb}}% + {% THEN W->E + \ifthenelse{\lengthtest{\tmp@Ya < \tmp@Yb}}% + {% THEN NW->SE + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{Bl} + \addtolength{\tmp@X}{\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{tr} + \addtolength{\tmp@X}{-\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + }{% ELSE + \ifthenelse{\lengthtest{\tmp@Ya > \tmp@Yb}}% + {% THEN SW -> NE + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{Br} + \addtolength{\tmp@X}{-\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{tl} + \addtolength{\tmp@X}{\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + }{% ELSE W->E + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{B} + \addtolength{\tmp@X}{0\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{t} + \addtolength{\tmp@X}{0\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + }% + }% + }{% ELSE + \ifthenelse{\lengthtest{\tmp@Xa > \tmp@Xb}}% + {% THEN E -> W + \ifthenelse{\lengthtest{\tmp@Ya < \tmp@Yb}}% + {% THEN NE -> SW + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{Br} + \addtolength{\tmp@X}{-\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{tl} + \addtolength{\tmp@X}{\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + }{% ELSE + \ifthenelse{\lengthtest{\tmp@Ya > \tmp@Yb}}% + {% THEN SE -> NW + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{Bl} + \addtolength{\tmp@X}{\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{tr} + \addtolength{\tmp@X}{-\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + }{% ELSE E -> W + \ifthenelse{\equal{\mess@labelposition}{t}}% + {\def\msc@labelrefpoint{B} + \addtolength{\tmp@X}{0\labeldist}% + \addtolength{\tmp@Y}{-\labeldist}% + }% + {\def\msc@labelrefpoint{t} + \addtolength{\tmp@X}{0\labeldist}% + \addtolength{\tmp@Y}{\labeldist}% + }% + } + } + }{% ELSE \tmp@Xa = \tmp@Xb (self message) + \ifthenelse{\equal{\mess@labelposition}{l}}% + {\def\msc@labelrefpoint{r} + \addtolength{\tmp@X}{-\labeldist}% + \addtolength{\tmp@Y}{0\labeldist}% + }% + {\def\msc@labelrefpoint{l} + \addtolength{\tmp@X}{\labeldist}% + \addtolength{\tmp@Y}{0\labeldist}% + }% + }% + }% +}% +\newcommand{\msc@labelbox}[1]{{#1}}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Genralized orders +% \order[pos]{sender}{receiver}[leveloffset][instanceoffset] +% +\newcommand{\order}[3][l]{% + \def\mess@style{order}% + \def\mess@linestyle{dashed}% + \def\selfmess@position{#1}% + \def\mess@labelposition{\ifx\mess@sender\mess@receiver l\else t\fi}% + \def\mess@labeltext{\relax}% + \def\mess@labelplacement{0.5}% + \def\mess@sender{#2}% + \def\mess@receiver{#3}% + \order@B% +} +\newcommand{\order@B}[1][\ifx\mess@sender\mess@receiver 1\else 0\fi]{% + \edef\mess@leveloffset{#1}% + \order@C% +} +\newcommand{\order@C}[1][0pt]{% + \def\mess@instanceoffset{#1}% + \msc@drawarrow% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% LOST and FOUND messages +% +% \lost[pos]{label}[labelpos]{gate}{sender}[placement] +% \found[pos]{label}[labelpos]{gate}{sender}[placement] +\newcommand{\lost}[1][l]{% + \def\lostfound@position{#1}% + %\def\msc@arrowdirection{->}% + \def\lostfound@type{lost}% + \def\msc@circlefillstyle{black}% + \lostfound@B% +} +\newcommand{\found}[1][l]{% + \def\lostfound@position{#1}% + %\def\msc@arrowdirection{<-}% + \def\lostfound@type{found}% + \def\msc@circlefillstyle{white}% + \lostfound@B% +} +\newcommand{\lostfound@B}[1]{% + \def\mess@style{mess}% + \def\mess@labeltext{#1}% + \lostfound@C% +} +\newcommand{\lostfound@C}[3][t]{% + \def\mess@labelposition{#1}% + \def\mess@gate{#2}% + \def\mess@sender{#3}% + \lostfound@D% +} +\newcommand{\lostfound@D}[1][0.5]{% + \def\mess@labelplacement{#1}% + \@lostfound% +} +% +% \@lostfound draws lost and found messages +\def\@lostfound{% + \expandafter\@ifundefined{mscinst\mess@sender}{% + \msc@instundefinederr{\mess@sender}}{% else, \mess@sender is defined + %\setlength{\tmp@Xa}{\msc@instxpos{\mess@sender}}% + \setlength{\tmp@Ya}{\msc@currentheight}% + \ifthenelse{\equal{\lostfound@position}{l}} + {% THEN put lost/found message left + \ifthenelse{\equal{\lostfound@type}{lost}}% + {% THEN + \setlength{\tmp@Xa}% start of arrow + {\msc@instlxpos{\mess@sender}}% + \setlength{\tmp@Xb}% end of arrow + {\tmp@Xa-\selfmesswidth}% + \setlength{\tmp@X}% label position + {\tmp@Xb + (\tmp@Xa - \tmp@Xb) * \real{\mess@labelplacement}}% + \setlength{\tmp@Xc}% circle position + {\tmp@Xb-\lostsymbolradius}% + }{% ELSE + \setlength{\tmp@Xb}% end of arrow + {\msc@instlxpos{\mess@sender}}% + \setlength{\tmp@Xa}% start of arrow + {\tmp@Xb-\selfmesswidth}% + \setlength{\tmp@X}% label position + {\tmp@Xa + (\tmp@Xb - \tmp@Xa) * \real{\mess@labelplacement}}% + \setlength{\tmp@Xc}% circle position + {\tmp@Xa-\lostsymbolradius}% + }% + \setlength{\tmp@Xd}% gate position + {\tmp@Xc-\lostsymbolradius-\labeldist}% + \def\msc@gaterefpoint{r}% + }{% ELSE, lost/found message right + \ifthenelse{\equal{\lostfound@type}{lost}}% + {% THEN + \setlength{\tmp@Xa}% start of arrow + {\msc@instrxpos{\mess@sender}}% + \setlength{\tmp@Xb}% end of arrow + {\tmp@Xa+\selfmesswidth}% + \setlength{\tmp@X}% label position + {\tmp@Xa + (\tmp@Xb - \tmp@Xa) * \real{\mess@labelplacement}}% + \setlength{\tmp@Xc}% circle position + {\tmp@Xb+\lostsymbolradius}% + }{% ELSE + \setlength{\tmp@Xb}% end of arrow + {\msc@instrxpos{\mess@sender}}% + \setlength{\tmp@Xa}% start of arrow + {\tmp@Xb+\selfmesswidth}% + \setlength{\tmp@X}% label position + {\tmp@Xb + (\tmp@Xa - \tmp@Xb) * \real{\mess@labelplacement}}% + \setlength{\tmp@Xc}% circle position + {\tmp@Xa+\lostsymbolradius}% + }% + \setlength{\tmp@Xd}% gate position + {\tmp@Xc+\lostsymbolradius+\labeldist}% + \def\msc@gaterefpoint{l}% + }% + \psline{->}(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)% + \ifthenelse{\equal{\mess@labelposition}{t}}% + {% THEN + \setlength{\tmp@Y}{\tmp@Ya-\lostsymbolradius-\labeldist}% + \def\msc@labelrefpoint{B}% + }{% ELSE + \ifthenelse{\equal{\mess@labelposition}{b}}% + {% THEN + \setlength{\tmp@Y}{\tmp@Ya+\lostsymbolradius+\labeldist}% + \def\msc@labelrefpoint{t}% + }{% ELSE + \msc@illegallostfoundlabelpositionerr{\mess@labelposition}% + }% + }% + \rput[\msc@labelrefpoint](\tmp@X,-\tmp@Y){\mess@labeltext}% + \pscircle[fillstyle=solid,fillcolor=\msc@circlefillstyle]% + (\tmp@Xc,-\tmp@Ya){\lostsymbolradius} + \rput[\msc@gaterefpoint](\tmp@Xd,-\tmp@Ya){\mess@gate}% + }% +} +% +% +% \settimer has one optional argument to define the position of +% the label of a self message. +\newcommand{\settimer}[1][l]{% + \msc@settimerpos{#1}% + \@timer{set}% +} +% +% +% \timeout has one optional argument to define the position of +% the label of a self message. +\newcommand{\timeout}[1][l]{% + \msc@settimerpos{#1}% + \@timer{timeout}% +} +% +% +% \stoptimer has one optional argument to define the position of +% the label of a self message. +\newcommand{\stoptimer}[1][l]{% + \msc@settimerpos{#1}% + \@timer{stop}% +} +% +% +% \settimeout has one optional argument to define the position of +% the label of a self message. +\newcommand{\settimeout}[1][l]{% + \msc@settimerpos{#1}% + \@timerdispatcher{settimeout}% +} +% +% +% \setstoptimer has one optional argument to define the position of +% the label of a self message. +\newcommand{\setstoptimer}[1][l]{% + \msc@settimerpos{#1}% + \@timerdispatcher{setstoptimer}% +} +\def\@timerdispatcher#1#2#3{% + \@ifnextchar[{\@oargtimerdispatcher{#1}{#2}{#3}}{\@nooargtimerdispatcher{#1}{#2}{#3}}} +% +\def\@oargtimerdispatcher#1#2#3[#4]{% + \msc@setleveloffset{#4}% + \@timer{#1}{#2}{#3}% +} +% +\def\@nooargtimerdispatcher#1#2#3{% + \msc@setleveloffset{2}% default level-offset value for combined timers + \@timer{#1}{#2}{#3}% +} +% +% +% \@timer draws timers +% #1: type of the timer (set/timeout/stop) +% #2: label +% #3: nickname of the instance +\def\@timer#1#2#3{% + \expandafter\@ifundefined{mscinst#3}{% + \msc@instundefinederr{#3}}{% else, #3 is defined + \setlength{\tmp@Xa}{\msc@instxpos{#3}}% + \setlength{\tmp@Ya}{\msc@currentheight}% + \ifthenelse{\equal{\msc@timerpos}{l}}{% point left of axis + \ifthenelse{\equal{\msc@instisfat{#3}}{true}}{% + \setlength{\tmp@Xa}{\msc@instlxpos{#3}}% + }{% + \relax% + }% + \setlength{\tmp@Xb}{\tmp@Xa-\selfmesswidth}% + }{ % else point right of axis + \ifthenelse{\equal{\msc@instisfat{#3}}{true}}{% + \setlength{\tmp@Xa}{\msc@instrxpos{#3}}% + }{% + \relax% + }% + \setlength{\tmp@Xb}{\tmp@Xa+\selfmesswidth}% + }% + \ifthenelse{\equal{#1}{timeout}}{% draw an arrow + \psline{<-}(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)% + }{ % else draw a line without arrow head + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)% + }% + \setlength{\tmp@X}{\tmp@Xb}% This looks clumsy - sm + \setlength{\tmp@Y}{\tmp@Ya}% + \msc@drawtimer{#1}{\tmp@X}{\tmp@Y}{\msc@timerpos}{#2}% + \ifthenelse{\equal{#1}{settimeout}}{% draw second part of settimeout + \setlength{\tmp@Ya}{\tmp@Y+\levelheight*\msc@leveloffset}% + \setlength{\tmp@Y}{\tmp@Y+0.75\timerwidth}% + \setlength{\tmp@Xa}{\msc@instxpos{#3}}% + \ifthenelse{\equal{\msc@timerpos}{l}}{% point left of axis + \ifthenelse{\equal{\msc@instisfat{#3}}{true}}{% + \setlength{\tmp@Xa}{\msc@instlxpos{#3}}% + }{% + \relax% + }% + }{ % else point right of axis + \ifthenelse{\equal{\msc@instisfat{#3}}{true}}{% + \setlength{\tmp@Xa}{\msc@instrxpos{#3}}% + }{% + \relax% + }% + } + \psline{->}(\tmp@X,-\tmp@Y)(\tmp@X,-\tmp@Ya)(\tmp@Xa,-\tmp@Ya)% + }{ % else not settimeout + \ifthenelse{\equal{#1}{setstoptimer}}{% draw second part of setstoptimer + \setlength{\tmp@Ya}{\tmp@Y+\levelheight*\msc@leveloffset}% + \setlength{\tmp@Y}{\tmp@Y+0.75\timerwidth}% + \setlength{\tmp@Xb}{\msc@instxpos{#3}}% + \ifthenelse{\equal{\msc@instisfat{#3}}{true}}{% + \ifthenelse{\equal{\msc@timerpos}{l}}{% point left of axis + \setlength{\tmp@Xb}{\msc@instlxpos{#3}}% + }{% point right of axis + \setlength{\tmp@Xb}{\msc@instrxpos{#3}}% + }% + }{% not a fat instance + \relax% + } + \psline(\tmp@X,-\tmp@Y)(\tmp@X,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)% + \setlength{\tmp@Y}{\tmp@Ya}% + \msc@drawtimer{stop}{\tmp@X}{\tmp@Y}{\msc@timerpos}{}% + }{ % else no second part needed + }% + }% + }% +} +% +% \msc@drawtimer draws the timer symbols +% #1: type of the timer (set/timeout/stop) +% #2: x-coordinate of center of timer +% #3: y-coordinate of center of timer +% #4: place text left (l) or right (r) +% #5: text added to the timer +\def\msc@drawtimer#1#2#3#4#5{% + \setlength{\tmp@Xa}{#2-0.5\timerwidth}% + \setlength{\tmp@Xb}{#2+0.5\timerwidth}% + \ifthenelse{\equal{#1}{stop}}{% draw reset symbol + \setlength{\tmp@Ya}{-#3+0.5\timerwidth}% + \setlength{\tmp@Yb}{-#3-0.5\timerwidth}% + \psline(\tmp@Xa,\tmp@Ya)(\tmp@Xb,\tmp@Yb)% + \psline(\tmp@Xb,\tmp@Ya)(\tmp@Xa,\tmp@Yb)% + }{% else draw set/timeout symbol + \setlength{\tmp@Ya}{-#3+0.75\timerwidth}% + \setlength{\tmp@Yb}{-#3-0.75\timerwidth}% + \psline(\tmp@Xa,\tmp@Ya)(\tmp@Xb,\tmp@Yb)% + (\tmp@Xa,\tmp@Yb)(\tmp@Xb,\tmp@Ya)(\tmp@Xa,\tmp@Ya)% + }% + \ifthenelse{\equal{#4}{l}}{% place label left + \setlength{\tmp@Xa}{#2-\labeldist-0.3ex}% + \setlength{\tmp@Ya}{-#3-0.5ex}% + \rput[B](\tmp@Xa,\tmp@Ya){\makebox[0pt][r]{#5}} + }{% else place label right + \setlength{\tmp@Xa}{#2+\labeldist+0.3ex}% + \setlength{\tmp@Ya}{-#3-0.5ex}% + \rput[B](\tmp@Xa,\tmp@Ya){\makebox[0pt][l]{#5}}% + }% +} +% +% +% \msc@drawinstancehead draws the head of the instance +% #1: nickname of the instance +\def\msc@drawinstancehead#1{% + \setlength{\tmp@Y}{\msc@currentheight}% + \msc@drawinstanceheadsymbol{#1}{\the\tmp@Y}% +} +% +% \msc@drawinstanceheadsymbol draw the head symbol of instance #1 at y-pos #2 +\def\msc@drawinstanceheadsymbol#1#2{% + \setlength{\tmp@X}{\msc@instxpos{#1}}% x-center head box + \setlength{\tmp@Y}{#2 + 0.5\instheadheight}% center of head symbol + \setlength{\tmp@Xa}{-0.5\instwidth+\tmp@X}% x-upperleft head box + \setlength{\tmp@Ya}{#2}% y-upperleft head box + \setlength{\tmp@Xb}{\tmp@Xa+\instwidth}% x-lowerright head box + \setlength{\tmp@Yb}{#2 + \instheadheight}% y-lowerright head box + \ifthenelse{\equal{\msc@insthead}{yes}}{% + \psframe[dimen=middle,linestyle=\msc@instlinestyle{#1}](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + }{% else, no head symbol drawing% + } + \rput[B](\tmp@X,-\tmp@Ya){\raisebox{\labeldist}{\makebox[0pt][c]{\msc@instabname{#1}}}}% + \rput[B](\tmp@X,-\tmp@Y){\raisebox{-.5ex}{\makebox[0pt][c]{\msc@instinname{#1}}}}% +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\msc@drawinstanceline#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + \ifthenelse{\equal{\msc@instypos{#1}}{undefined}}{% y-pos undefined: no line needed + }{% else + \setlength{\tmp@Ya}{\msc@instypos{#1}}% + \setlength{\tmp@Yb}{\msc@currentheight}% + \ifthenelse{\equal{true}{\msc@instisfat{#1}}}% + {% fat instance + \setlength{\tmp@Xa}{\msc@instlxpos{#1}}% + \setlength{\tmp@Xb}{\msc@instrxpos{#1}}% + \ifthenelse{\equal{\msc@instregionstyle{#1}}{coregion}} + {% + \psline[linestyle=dashed](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=dashed](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + {\ifthenelse{\equal{\msc@instregionstyle{#1}}{suspension}} + {% + \psline[linestyle=dashed,dash=7pt 7pt](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=dashed,dash=7pt 7pt](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + {\ifthenelse{\equal{\msc@instregionstyle{#1}}{activation}} + {% + \psframe[dimen=middle,fillstyle=solid,fillcolor=lightgray](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb) + \psline[linestyle=solid](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=solid](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + {% normal region: + \psline[linestyle=solid](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=solid](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + } + } + } + {% normal instance (not fat) + \setlength{\tmp@X}{\msc@instxpos{#1}}% + \ifthenelse{\equal{\msc@instregionstyle{#1}}{coregion}} + {% + \psline[linestyle=dashed](\tmp@X,-\tmp@Ya)(\tmp@X,-\tmp@Yb)% + } + {\ifthenelse{\equal{\msc@instregionstyle{#1}}{suspension}} + {% + \setlength{\tmp@X}{\regionbarwidth} + \setlength{\tmp@Xa}{\msc@instxpos{#1} - 0.5\tmp@X}% + \setlength{\tmp@Xb}{\msc@instxpos{#1} + 0.5\tmp@X}% + \psline[linestyle=dashed,dash=7pt 7pt](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=dashed,dash=7pt 7pt](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + {\ifthenelse{\equal{\msc@instregionstyle{#1}}{activation}} + {% + \setlength{\tmp@X}{\regionbarwidth} + \setlength{\tmp@Xa}{\msc@instxpos{#1} - 0.5\tmp@X}% + \setlength{\tmp@Xb}{\msc@instxpos{#1} + 0.5\tmp@X}% + \psframe[dimen=middle,fillstyle=solid,fillcolor=lightgray](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb) + \psline[linestyle=solid](\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + \psline[linestyle=solid](\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + } + {% normal region + \psline[linestyle=\msc@instlinestyle{#1}](\tmp@X,-\tmp@Ya)(\tmp@X,-\tmp@Yb)% + } + } + } + }% + }% + }% +}% +% +% \msc@drawinstancefoot draws the last level and foot of the instance +% #1: nickname of the instance +\def\msc@drawinstancefoot#1{% + \setlength{\tmp@Y}{\msc@currentheight}% + \msc@drawinstancefootsymbol{#1}{\the\tmp@Y}% +} +% +% \msc@drawinstancefootsymbol draws a footer symbol for instance #1 at y-pos #2. +\def\msc@drawinstancefootsymbol#1#2{% + \setlength{\tmp@Xa}{-0.5\instwidth+\msc@instxpos{#1}}% + \setlength{\tmp@Ya}{\msc@currentheight}% + \setlength{\tmp@Xb}{\tmp@Xa+\instwidth}% + \setlength{\tmp@Yb}{#2 + \instfootheight}% + \ifthenelse{\equal{\msc@instfoot}{yes}}{ + \psframe[dimen=middle,fillstyle=solid,fillcolor=\msc@instfootcolor{#1},linestyle=\msc@instlinestyle{#1}](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + }{% else, no foot symbol drawing% + } +} +% +% \nextlevel incresaes \msc@currentheight by #1 * \levelheight +% (optional) #1: a nonnegative integer number (defaults to 1) +% +\newcommand{\nextlevel}[1][1]{% + \addtolength{\msc@currentheight}{#1\levelheight}% +} +% +\def\msc@drawinstancefooters{% + \ifthenelse{\value{tmpcnt} < \value{mscinstcnt}}{% + % Only draw the instancefoot if the instypos is defined (not ``undefined'') + % This signals a previous instance stop. + \ifthenelse{\equal{\msc@instypos{\msc@instnickname{tmpcnt}}}{undefined}}{\relax}{% + \msc@drawinstanceline{\msc@instnickname{tmpcnt}}% + \msc@drawinstancefoot{\msc@instnickname{tmpcnt}}% + }% + \msc@incrcounter{tmpcnt}% + \msc@drawinstancefooters}{% else nothing + }% +}% +% +% \action puts an action symbol on the instance with nickname #2. +% The action symbol will be placed on the current level and the text #1 +% is centered inside the action symbol. +\def\action#1#2{% + \expandafter\@ifundefined{mscinst#2}{% + \msc@instundefinederr{#2}}{% else, #2 is defined + % first, draw the instance line as far as possible + \msc@drawinstanceline{#2}% + % then, draw the action symbol + % if #2's bar width is greater than the action width, the width of this + % action will be the instnce bar width. + \ifthenelse{\lengthtest{\msc@instbarwidth{#2}<\actionwidth}}% + {\setlength{\tmp@X}{\actionwidth}}% + {\setlength{\tmp@X}{\msc@instbarwidth{#2}}}% + \setlength{\tmp@Xa}{\msc@instxpos{#2}-0.5\tmp@X}% + \setlength{\tmp@Xb}{\tmp@Xa+\tmp@X}% + \setlength{\tmp@Ya}{\msc@currentheight}% + \setlength{\tmp@Yb}{\tmp@Ya+\actionheight}% + \psframe[dimen=middle](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + \setlength{\tmp@X}{\msc@instxpos{#2}}% + \setlength{\tmp@Y}{\tmp@Ya+0.5\actionheight}% + \rput[B](\tmp@X,-\tmp@Y){\raisebox{-.5ex}{\makebox[0pt][c]{#1}}}% + % redefine the instance's y position + \setlength{\tmp@Y}{\msc@currentheight+\actionheight}% + \msc@setinstypos{#2}{\the\tmp@Y}% + }% +} +% +% \stop ends the instance with nickname #1. +\def\stop#1{% + \expandafter\@ifundefined{mscinst#1}{% + \msc@instundefinederr{#1}}{% else, #1 is defined + % first, draw the instance line as far as possible + \msc@drawinstanceline{#1}% + \setlength{\tmp@Yb}{\msc@currentheight}% + % close the instance axis if it is a fat instance + \ifthenelse{\equal{true}{\msc@instisfat{#1}}}% + {% + \setlength{\tmp@Xa}{\msc@instlxpos{#1}}% + \setlength{\tmp@Xb}{\msc@instrxpos{#1}}% + \psline(\tmp@Xa,-\tmp@Yb)(\tmp@Xb,-\tmp@Yb)% + }% + {% else it is not fat + }% + % then, draw the stop symbol + \setlength{\tmp@X}{\msc@instxpos{#1}}% + \setlength{\tmp@Xa}{\tmp@X-0.5\stopwidth}% + \setlength{\tmp@Xb}{\tmp@X+0.5\stopwidth}% + \setlength{\tmp@Ya}{\tmp@Yb+0.5\stopwidth}% + \setlength{\tmp@Yb}{\tmp@Yb-0.5\stopwidth}% + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% + \psline(\tmp@Xb,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb)% + % redefine the instance's y position + % ``undefined'' means that the instance axis will not be drawn any further + \msc@setinstypos{#1}{undefined}% + }% +} +% +% +% \condition puts a condition symbol over the given instances +% #1: name to be put inside the condition symbol +% #2: comma-separated list of instance nicknames, such that: +% - The first instance nickname is supposed to be the leftmost +% instance of the condition +% - The last instance nickname is supposed to be the rightmost +% instance of the condition +\def\condition#1#2{% + \def\msc@conditiontext{#1}% + \def\msc@firstconditioninst{undefined}% + \def\msc@lastconditioninst{undefined}% + \msc@condition{#2}% +% debugging info: +% \message{(msc: condition: \msc@firstconditioninst...\msc@lastconditioninst)}% + \ifthenelse{\equal{\msc@instisfat{\msc@firstconditioninst}}{true}}{% + \setlength{\tmp@Xa}{\msc@instlxpos{\msc@firstconditioninst}-\conditionoverlap}% + }{% + \setlength{\tmp@Xa}{\msc@instxpos{\msc@firstconditioninst}-\conditionoverlap}% + }% + \setlength{\tmp@Ya}{\msc@currentheight}% + \ifthenelse{\equal{\msc@instisfat{\msc@lastconditioninst}}{true}}{% + \setlength{\tmp@Xb}{\msc@instrxpos{\msc@lastconditioninst}+\conditionoverlap}% + }{% + \setlength{\tmp@Xb}{\msc@instxpos{\msc@lastconditioninst}+\conditionoverlap}% + }% + \setlength{\tmp@Yb}{\tmp@Ya+\conditionheight}% + \msc@drawcondition{#1}{\tmp@Xa}{\tmp@Ya}{\tmp@Xb}{\tmp@Yb}% +} +% +\def\msc@condition#1{% + \@for\msccondition@rg:=#1\do{% + \expandafter\@ifundefined{mscinst\msccondition@rg}{% + \msc@instundefinederr{\msccondition@rg}}{% else, \msccondition@rg is defined +% debugging info: +% \message{(msc: condition instance "\msccondition@rg")}% + \ifthenelse{\equal{\msc@firstconditioninst}{undefined}}{% + \edef\msc@firstconditioninst{\msccondition@rg}% + }{\ifthenelse{\lengthtest{\msc@instxpos{\msc@firstconditioninst} > \msc@instxpos{\msccondition@rg}}}{% + \edef\msc@firstconditioninst{\msccondition@rg}}{}% + }% + \ifthenelse{\equal{\msc@lastconditioninst}{undefined}}{% + \edef\msc@lastconditioninst{\msccondition@rg}% + }{\ifthenelse{\lengthtest{\msc@instxpos{\msc@lastconditioninst} < \msc@instxpos{\msccondition@rg}}}{% + \edef\msc@lastconditioninst{\msccondition@rg}}{}% + } + % now, draw the instance line as far as possible + \msc@drawinstanceline{\msccondition@rg}% + % \setlength{\tmp@X}{\msc@instxpos{\msccondition@rg}}% + % \setlength{\tmp@Ya}{\msc@instypos{\msccondition@rg}}% + % \setlength{\tmp@Yb}{\msc@currentheight+\msc@headoffset}% + % \psline[linestyle=\msc@instlinestyle{\msccondition@rg}](\tmp@X,-\tmp@Ya)(\tmp@X,-\tmp@Yb)% + % and redefine the instance's y position + \setlength{\tmp@Y}{\msc@currentheight+\conditionheight}% + \msc@setinstypos{\msccondition@rg}{\the\tmp@Y}% + }% + }% +} +% +% \msc@drawcondition draw the condition symbol +% #1: condition-text +\def\msc@drawcondition#1#2#3#4#5{% + \setlength{\tmp@Xc}{#4+ .6#5 - .6#3}% + \setlength{\tmp@Yc}{.5#3 + .5#5}% + \psline(#2,-#3)(#4,-#3)(\tmp@Xc,-\tmp@Yc)(#4,-#5)% + \setlength{\tmp@Xc}{#2- .6#5 + .6#3}% + \psline(#4,-#5)(#2,-#5)(\tmp@Xc,-\tmp@Yc)(#2,-#3)% + \setlength{\tmp@Xc}{.5#2 + .5#4}% + \setlength{\tmp@Yc}{.5#3 + .5#5}% + \rput[B](\tmp@Xc,-\tmp@Yc){\raisebox{-.5ex}{\makebox[0pt][c]{#1}}}% +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% GATES +% \gate[hpos][vpos]{text}{nickname}[h-offset] +% \gate*[hpos][vpos]{text}{nickname}[h-offset] +% (starred version puts a dot at the position of the gate on the instance line) +% +% hpos: optional horizontal position argument l(eft) or r(ight). default: l +% vpos: optional vertical position argument t(op), c(enter) or b(ottom). default: t +% text: text to be placed at the gate +% nickname: nickname of the instance to which the gate belongs +% +\def\gate{\@ifstar{\def\msc@gatestar{defined}\msc@gateh}{\def\msc@gatestar{undefined}\msc@gateh}} +\newcommand{\msc@gateh}[1][l]{% + \def\msc@gatehpos{#1}% + \msc@gatev% +} +% +\newcommand{\msc@gatev}[3][t]{% + \msc@gate{#1}{#2}{#3}% +} +% +\def\msc@gate#1#2#3{% + \expandafter\@ifundefined{mscinst#3}{% + \msc@instundefinederr{#3}}{% else, #3 is defined + \ifthenelse{\equal{\msc@instisfat{#3}}{true}} + {\ifthenelse{\equal{\msc@gatehpos}{l}} + {\setlength{\tmp@X}{\msc@instlxpos{#3}}} + {\setlength{\tmp@X}{\msc@instrxpos{#3}}} + }% + {\setlength{\tmp@X}{\msc@instxpos{#3}}} + \ifthenelse{\equal{\msc@gatestar}{defined}}{% + \setlength{\tmp@Y}{\msc@currentheight}% + \pscircle[fillstyle=solid,fillcolor=black](\tmp@X,-\tmp@Y){.5mm}}{}% + \ifthenelse{\equal{t}{#1}}{ + \setlength{\tmp@Y}{\msc@currentheight - \labeldist}% + \def\msc@gatetext{{#2}}% + }{% + \ifthenelse{\equal{c}{#1}}{% + \setlength{\tmp@Y}{\msc@currentheight}% + \def\msc@gatetext{\raisebox{-.5\totalheight}{#2}}% + }{% + \setlength{\tmp@Y}{\msc@currentheight + \labeldist}% + \def\msc@gatetext{\raisebox{-\totalheight}{#2}}% + }}% + \ifthenelse{\equal{l}{\msc@gatehpos}}{% + \addtolength{\tmp@X}{-\labeldist}% + \rput[B](\tmp@X,-\tmp@Y){\makebox[0pt][r]{\msc@gatetext}}}% + {% + \addtolength{\tmp@X}{\labeldist}% + \rput[B](\tmp@X,-\tmp@Y){\makebox[0pt][l]{\msc@gatetext}}% + }% + } +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MSC COMMENTS +% +% +% \msccomment[#1]{#2}{#3} +% #1: position l/r or a distance +% #2: text +% #3: instance nick name +\newcommand{\msccomment}[3][l]{% + \expandafter\@ifundefined{mscinst#3}{% + \msc@instundefinederr{#3}} + {% else, #3 is defined + \ifthenelse{\equal{#1}{l}}% + {\setlength{\msc@commentdist}{-\msccommentdist}}% + {\ifthenelse{\equal{#1}{r}}% + {\setlength{\msc@commentdist}{\msccommentdist}}% + {\setlength{\msc@commentdist}{#1}}% + } + \savebox{\tmp@box}{\raisebox{\depth}[\totalheight][0pt]{#2}}% + \setlength{\tmp@Y}{\msc@currentheight}% + \setlength{\tmp@Ya}{\tmp@Y + .5\ht\tmp@box}% + \addtolength{\tmp@Ya}{\labeldist}% + \setlength{\tmp@Yb}{\tmp@Y - .5\ht\tmp@box}% + \addtolength{\tmp@Yb}{-\labeldist}% +% \message{( a: \the\tmp@Ya, b: \the\tmp@Yb)} + \ifthenelse{\lengthtest{\msc@commentdist < 0pt}}% + {% comment left from instance #3 + \setlength{\tmp@X}{\msc@instlxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X + \msc@commentdist} + \psline(\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Y) + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb) + \setlength{\tmp@Xb}{\wd\tmp@box} + \setlength{\tmp@Xb}{\tmp@Xa - \tmp@Xb} + \addtolength{\tmp@Xb}{-\labeldist} + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \psline(\tmp@Xa,-\tmp@Yb)(\tmp@Xb,-\tmp@Yb) + \addtolength{\tmp@Xa}{-\labeldist} + \rput[r](\tmp@Xa,-\tmp@Y){#2}% + }% + {% comment right from instance #3 + \setlength{\tmp@X}{\msc@instrxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X + \msc@commentdist} + \psline(\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Y) + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xa,-\tmp@Yb) + \setlength{\tmp@Xb}{\wd\tmp@box} + \setlength{\tmp@Xb}{\tmp@Xa + \tmp@Xb} + \addtolength{\tmp@Xb}{\labeldist} + \psline(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \psline(\tmp@Xa,-\tmp@Yb)(\tmp@Xb,-\tmp@Yb) + \addtolength{\tmp@Xa}{\labeldist} + \rput[l](\tmp@Xa,-\tmp@Y){\usebox{\tmp@box}} + }% + }% +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MSC MARKS +% +% \mark[#1]{#2}{#3} +% #1: placement: tl,bl,tr,br +% #2: text +% #3: instance nick name +% +\newcommand{\mscmark}[3][tl]{% + \expandafter\@ifundefined{mscinst#3}{% + \msc@instundefinederr{#3}} + {% else, #3 is defined + \savebox{\tmp@box}{\raisebox{\depth}[\totalheight][0pt]{#2}} + \ifthenelse{\equal{#1}{tl}} + {%tl: + \setlength{\tmp@X}{\msc@instlxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X - \markdist} + \setlength{\tmp@Xb}{\tmp@Xa - \wd\tmp@box - 2\labeldist} + \setlength{\tmp@Y}{\msc@currentheight} + \setlength{\tmp@Ya}{\msc@currentheight - .5\markdist} + \psline[linestyle=dashed](\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \setlength{\tmp@Xb}{\tmp@Xa - \labeldist - .5\wd\tmp@box} + \addtolength{\tmp@Ya}{-\labeldist} + \rput[b](\tmp@Xb,-\tmp@Ya){\usebox{\tmp@box}} + }{ + \ifthenelse{\equal{#1}{bl}} + {%tl: + \setlength{\tmp@X}{\msc@instlxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X - \markdist} + \setlength{\tmp@Xb}{\tmp@Xa - \wd\tmp@box - 2\labeldist} + \setlength{\tmp@Y}{\msc@currentheight} + \setlength{\tmp@Ya}{\msc@currentheight + .5\markdist} + \psline[linestyle=dashed](\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \setlength{\tmp@Xb}{\tmp@Xa - \labeldist - .5\wd\tmp@box} + \addtolength{\tmp@Ya}{-\labeldist} + \rput[b](\tmp@Xb,-\tmp@Ya){\usebox{\tmp@box}} + }{ + \ifthenelse{\equal{#1}{tr}} + {%bl: + \setlength{\tmp@X}{\msc@instrxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X + \markdist} + \setlength{\tmp@Xb}{\tmp@Xa + \wd\tmp@box + 2\labeldist} + \setlength{\tmp@Y}{\msc@currentheight} + \setlength{\tmp@Ya}{\msc@currentheight - .5\markdist} + \psline[linestyle=dashed](\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \setlength{\tmp@Xb}{\tmp@Xa + \labeldist + .5\wd\tmp@box} + \addtolength{\tmp@Ya}{-\labeldist} + \rput[b](\tmp@Xb,-\tmp@Ya){\usebox{\tmp@box}} + }{ + \ifthenelse{\equal{#1}{br}} + {%tl: + \setlength{\tmp@X}{\msc@instrxpos{#3}} + \setlength{\tmp@Xa}{\tmp@X + \markdist} + \setlength{\tmp@Xb}{\tmp@Xa + \wd\tmp@box + 2\labeldist} + \setlength{\tmp@Y}{\msc@currentheight} + \setlength{\tmp@Ya}{\msc@currentheight + .5\markdist} + \psline[linestyle=dashed](\tmp@X,-\tmp@Y)(\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya) + \setlength{\tmp@Xb}{\tmp@Xa + \labeldist + .5\wd\tmp@box} + \addtolength{\tmp@Ya}{-\labeldist} + \rput[b](\tmp@Xb,-\tmp@Ya){\usebox{\tmp@box}} + }{ + \msc@illegalmarkplacement{#1} + }}}}} +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MSC MEASURES +% +% +\newlength{\msc@measuredist}% internal length for horizontal measure distance +% \measure[*][#1]{#2}{#3}{#4}[#5] +% *: the starred version puts the top measure mark above and the bottom measure mark +% below the measure position. +% #1: placement: l (left) r (right), or distance (negative or positive) to closest of #3 or #4 +% #2: name +% #3: instance nick name +% #4: instance nick name +% #5: (vertical) offset +\newcommand{\measure}{% + \@ifstar{\def\msc@innermeasure{false}\msc@measureargs} + {\def\msc@innermeasure{true}\msc@measureargs}% +} +% +\newcommand{\msc@measureargs}[4][l]{% + \def\msc@i{#1}% + \def\msc@ii{#2}% + \def\msc@iii{#3}% + \def\msc@iv{#4}% + \msc@measureoffset% +} + +\newcommand{\msc@measureoffset}[1][1]{% + \def\msc@mscv{#1}% + \msc@measure{\msc@i}{\msc@ii}{\msc@iii}{\msc@iv}{\msc@mscv} +} + +\newcommand{\msc@measure}[5]{% + \ifthenelse{\equal{#1}{l}} + {\setlength{\msc@measuredist}{-\measuredist}} + {\ifthenelse{\equal{#1}{r}} + {\setlength{\msc@measuredist}{\measuredist}} + {\setlength{\msc@measuredist}{#1}}} + % + \setlength{\tmp@Ya}{\msc@currentheight} + \setlength{\tmp@Yb}{\tmp@Ya + #5\levelheight} + \setlength{\tmp@Y}{.5\tmp@Ya + .5\tmp@Yb} + \ifthenelse{\lengthtest{\msc@instxpos{#3} < \msc@instxpos{#4}}} + {% + \ifthenelse{\lengthtest{\msc@measuredist < 0pt}} + {% left from instances + \setlength{\tmp@Xa}{\msc@instlxpos{#3}} + \setlength{\tmp@Xb}{\msc@instlxpos{#4}} + \setlength{\tmp@X}{\tmp@Xa + \msc@measuredist} + } + {% right from instances + \setlength{\tmp@Xa}{\msc@instrxpos{#3}} + \setlength{\tmp@Xb}{\msc@instrxpos{#4}} + \setlength{\tmp@X}{\tmp@Xb + \msc@measuredist} + } + } + {% + \ifthenelse{\lengthtest{\msc@measuredist < 0pt}} + {% left from instances + \setlength{\tmp@Xa}{\msc@instlxpos{#3}} + \setlength{\tmp@Xb}{\msc@instlxpos{#4}} + \setlength{\tmp@X}{\tmp@Xb + \msc@measuredist} + } + {% right from instances + \setlength{\tmp@Xa}{\msc@instrxpos{#3}} + \setlength{\tmp@Xb}{\msc@instrxpos{#4}} + \setlength{\tmp@X}{\tmp@Xa + \msc@measuredist} + } + } + \psline[linestyle=dashed](\tmp@Xa,-\tmp@Ya)(\tmp@X,-\tmp@Ya)(\tmp@X,-\tmp@Yb)(\tmp@Xb,-\tmp@Yb) + \ifthenelse{\lengthtest{\msc@measuredist < 0pt}} + {% left from instances + \addtolength{\tmp@X}{-\labeldist} + \rput[r](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \addtolength{\tmp@X}{\labeldist} + } + {% right from instances + \addtolength{\tmp@X}{\labeldist} + \rput[l](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \addtolength{\tmp@X}{-\labeldist} + } + \ifthenelse{\equal{\msc@innermeasure}{true}} + {% + \msc@measuresymbolup{\tmp@X}{\tmp@Ya} + \msc@measuresymboldown{\tmp@X}{\tmp@Yb} + } + {% + \msc@measuresymboldown{\tmp@X}{\tmp@Ya} + \msc@measuresymbolup{\tmp@X}{\tmp@Yb} + } +} +% +% +% \measurestart[*][#1]{#2}{#3}{#4} +% *: unstarred/starred version draws downward/upward triangle +% #1: placement: l (left) r (right), or distance (negative or positive) to #3 +% #2: name +% #3: instance nick name +% #4: gate name +\newcommand{\measurestart}{% + \@ifstar{\def\msc@innermeasure{false}\msc@measurestartargs} + {\def\msc@innermeasure{true}\msc@measurestartargs} +} +% +% +\newcommand{\msc@measurestartargs}[4][l]{% + \def\msc@i{#1}% + \def\msc@ii{#2}% + \def\msc@iii{#3}% + \def\msc@iv{#4}% + \msc@measurestartoffset% +} + +\newcommand{\msc@measurestartoffset}[1][2]{% + \msc@measurestart{\msc@i}{\msc@ii}{\msc@iii}{\msc@iv}{#1}% +} +% +\newcommand{\msc@measurestart}[5]{% + \ifthenelse{\equal{#1}{l}} + {\setlength{\msc@measuredist}{-\measuredist}} + {\ifthenelse{\equal{#1}{r}} + {\setlength{\msc@measuredist}{\measuredist}} + {\setlength{\msc@measuredist}{#1}}} + \setlength{\tmp@Ya}{\msc@currentheight} + \ifthenelse{\lengthtest{\msc@measuredist < 0pt}} + {% left from instance + \setlength{\tmp@Xa}{\msc@instlxpos{#3}} + \setlength{\tmp@Xb}{\tmp@Xa + \msc@measuredist} + \setlength{\tmp@Yb}{\tmp@Ya + #5\levelheight} + \setlength{\tmp@X}{\tmp@Xb - \labeldist - 0.5\measuresymbolwidth} + \setlength{\tmp@Y}{.5\tmp@Ya + .5\tmp@Yb} + \rput[r](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \setlength{\tmp@Y}{\tmp@Yb + \labeldist} + \rput[r](\tmp@X,-\tmp@Yb){\raisebox{\depth}[\totalheight][0pt]{#4}} + } + {% right from instance + \setlength{\tmp@Xa}{\msc@instrxpos{#3}} + \setlength{\tmp@Xb}{\tmp@Xa + \msc@measuredist} + \setlength{\tmp@Yb}{\tmp@Ya + #5\levelheight} + \setlength{\tmp@X}{\tmp@Xb + \labeldist + 0.5\measuresymbolwidth} + \setlength{\tmp@Y}{.5\tmp@Ya + .5\tmp@Yb} + \rput[l](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \setlength{\tmp@Y}{\tmp@Yb + \labeldist} + \rput[l](\tmp@X,-\tmp@Yb){\raisebox{\depth}[\totalheight][0pt]{#4}} + } + \psline[linestyle=dashed](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb) + \ifthenelse{\equal{\msc@innermeasure}{true}} + {\msc@measuresymbolup{\tmp@Xb}{\tmp@Ya}} + {\msc@measuresymboldown{\tmp@Xb}{\tmp@Ya}} + \rput(\tmp@Xb,-\tmp@Yb){\pscircle[fillcolor=white,fillstyle=solid](0,0){.5\measuresymbolwidth}} + } +% +% \measureend[*][#1]{#2}{#3}{#4} +% *: unstarred/starred version draws upward/downward triangle +% #1: placement: l (left) r (right), or distance (negative or positive) to #3 +% #2: name +% #3: instance nick name +% #4: gate name +\newcommand{\measureend}{% + \@ifstar{\def\msc@innermeasure{false}\msc@measureendargs}% + {\def\msc@innermeasure{true}\msc@measureendargs}% +} +% +\newcommand{\msc@measureendargs}[4][l]{% + \def\msc@i{#1}% + \def\msc@ii{#2}% + \def\msc@iii{#3}% + \def\msc@iv{#4}% + \msc@measureendoffset% +} +% +\newcommand{\msc@measureendoffset}[1][2]{% + \msc@measureend{\msc@i}{\msc@ii}{\msc@iii}{\msc@iv}{#1}% +} +% +\newcommand{\msc@measureend}[5]{% + \ifthenelse{\equal{#1}{l}} + {\setlength{\msc@measuredist}{-\measuredist}} + {\ifthenelse{\equal{#1}{r}} + {\setlength{\msc@measuredist}{\measuredist}} + {\setlength{\msc@measuredist}{#1}}} + \setlength{\tmp@Ya}{\msc@currentheight} + \ifthenelse{\lengthtest{\msc@measuredist < 0pt}} + {% left from instance + \setlength{\tmp@Xa}{\msc@instlxpos{#3}} + \setlength{\tmp@Xb}{\tmp@Xa + \msc@measuredist} + \setlength{\tmp@Yb}{\tmp@Ya - #5\levelheight} + \setlength{\tmp@X}{\tmp@Xb - \labeldist - 0.5\measuresymbolwidth} + \setlength{\tmp@Y}{.5\tmp@Ya + .5\tmp@Yb} + \rput[r](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \setlength{\tmp@Y}{\tmp@Yb - \labeldist} + \rput[r](\tmp@X,-\tmp@Yb){\raisebox{\depth}[\totalheight][0pt]{#4}} + } + {% right from instance + \setlength{\tmp@Xa}{\msc@instrxpos{#3}} + \setlength{\tmp@Xb}{\tmp@Xa + \msc@measuredist} + \setlength{\tmp@Yb}{\tmp@Ya - #5\levelheight} + \setlength{\tmp@X}{\tmp@Xb + \labeldist + 0.5\measuresymbolwidth} + \setlength{\tmp@Y}{.5\tmp@Ya + .5\tmp@Yb} + \rput[l](\tmp@X,-\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{#2}} + \setlength{\tmp@Y}{\tmp@Yb - \labeldist} + \rput[l](\tmp@X,-\tmp@Yb){\raisebox{\depth}[\totalheight][0pt]{#4}} + } + \psline[linestyle=dashed](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb) + \ifthenelse{\equal{\msc@innermeasure}{true}} + {\msc@measuresymboldown{\tmp@Xb}{\tmp@Ya}} + {\msc@measuresymbolup{\tmp@Xb}{\tmp@Ya}} + \rput(\tmp@Xb,-\tmp@Yb){\pscircle[fillcolor=white,fillstyle=solid](0,0){.5\measuresymbolwidth}} + } +% +% measure symbols +% +\def\msc@measuresymbolup#1#2{% + % sin(pi/3) =~ 0.866025403784 + % draw an upward triangle with 60-degree (pi/3) angles and base at (#1,#2) + \rput[t](#1,-#2){% + \begin{pspicture}(-1,0)(1,0.866025403784\measuresymbolwidth)% + \pstriangle[dimen=middle,fillcolor=white,fillstyle=solid](\measuresymbolwidth,0.866025403784\measuresymbolwidth)% + \end{pspicture}% + } +} +% +\def\msc@measuresymboldown#1#2{% + % sin(pi/3) =~ 0.866025403784 + % draw a downward triangle with 60-degree (pi/3) angles and base at (#1,#2) + \rput[b](#1,-#2){% + \begin{pspicture}(-1,0)(1,-0.866025403784\measuresymbolwidth)% + \pstriangle[dimen=middle,fillcolor=white,fillstyle=solid](\measuresymbolwidth,-0.866025403784\measuresymbolwidth)% + \end{pspicture}% + } +} + +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \drawmscframe draws a frame of the right size around the msc +% This command also set the value of \msc@totalsizebox +\def\msc@drawframe{% + \ifthenelse{\equal{\msc@frame}{yes}}{% + \psframe[dimen=middle](0,0)(\msc@currentwidth,-\msc@currentheight)% + }{% no frame drawing + }% +} +% +% \msckeyword is the keyword representation of msc +\def\msckeyword{msc} +\def\msckeywordstyle#1{\textbf{#1}} +% +% This keyword can be changed by the \setmsckeyword command (or by \renewcommand{\msckeyword}{...}): +\newcommand{\setmsckeyword}[1]{\def\msckeyword{#1}} +\newcommand{\setmsckeywordstyle}[1]{\def\msckeywordstyle{#1}}% +% +% Commands to switch internal options that control the drawing of header and footer symbols +\newcommand{\drawinsthead}[1]{\def\msc@insthead{#1}}% +\drawinsthead{yes}% +\newcommand{\drawinstfoot}[1]{\def\msc@instfoot{#1}}% +\drawinstfoot{yes}% +% A similar command to control drawing of the msc-frame +\newcommand{\drawframe}[1]{\def\msc@frame{#1}}% +\drawframe{yes}% +% +% +\def\msc@grid{no}% +\newcommand{\showgrid}{\def\msc@grid{yes}} +\newcommand{\nogrid}{\def\msc@grid{no}} + + +\def\msc@settitle{% +\MSC@settitle{msc}% + {0\mscunit}% + {-\msc@totalheight}% + {\msc@totalwidth}% + {0\mscunit}% + {\msc@titlejustification}% + {\msckeywordstyle{\msckeyword}{} \msc@title}% +} + +% +% \msc@title stores the title given in \begin{msc}{title} +\def\msc@title{}% +% +% \msc@titlejustification says how the title should be justified +% Justification is relative to the total width of the msc +% l: left (default) +% c: centered +% r: right +% +\newsavebox{\mscbox}% +% +% the msc-environment +\newenvironment{msc}[2][l]{% +\message{(\msckeyword: '#2'}% +\def\msc@titlejustification{#1}% +\def\msc@title{#2}% +\setcounter{mscinstcnt}{0}% +\setlength{\msc@currentheight}{\topheaddist}% +\addtolength{\msc@currentheight}{\instheadheight}% +\addtolength{\msc@currentheight}{\firstlevelheight}% +\setlength{\msc@currentwidth}{0pt}% +% define the artificial left and right environment instances +\msc@declinst{envleft}{}{}{\the\instbarwidth}% +\msc@setinstxpos{envleft}{0pt}% +\msc@declinst{envright}{}{}{\the\instbarwidth}% +\msc@setinstxpos{envright}{\envinstdist}% +\begin{lrbox}{\mscbox}% +\begin{pspicture}(0,0)% we draw the msc in a picture of size 0x0 +\psset{dash=4pt 4pt}% sets the hashed linestyle style +}{% + \addtolength{\msc@currentheight}{\lastlevelheight}% + \setcounter{tmpcnt}{2}% + \msc@drawinstancefooters% +% If there is at least one instance, the current width is +% set to the xpos of the NEXT msc instance. There is at least one instance, +% if mscinstcnt >= 2. So, in that case, we have to +% substract one \instdist from the current width. +% +%\ifthenelse{\value{mscinstcnt}<2}{% no user defined instances, so, relax +% \relax% +%}{% mscinstcnt >= 2 +% \addtolength{\msc@currentwidth}{-\instdist}% +%}% +% Now we compute the final current width: one extra \envinstdist: +\setlength{\msc@currentwidth}{\msc@instxpos{envright}}% +\addtolength{\msc@currentheight}{\instfootheight+\bottomfootdist}% +\msc@drawframe% +\global\msc@totalwidth=\msc@currentwidth% +\global\msc@totalheight=\msc@currentheight% +\ifthenelse{\equal{\msc@grid}{yes}}{% + \psgrid[subgriddiv=1,griddots=10](0,0)(0,0)(\msc@currentwidth,-\msc@currentheight)% +}{\relax}% +\msc@settitle% +\end{pspicture}% +% Debug info: +%\typeout{msc size: \the\msc@totalwidth x\the\msc@totalheight}% +\end{lrbox}% +% the \mscbox now contains a box of 0x0, however the actual width and +% height are stored in \msc@total{width,height}. We use these lengths +% to adjust the width and height of the \mscbox +\wd\mscbox=\msc@totalwidth% +\ht\mscbox=\msc@totalheight% +\dp\mscbox=0pt% +% Now the \mscbox can be scaled (by \mscscalefactor) and `printed': +{% DEBUG: use this \fbox stuf to check the bounding box + \setlength{\fboxrule}{0.01pt}% + \setlength{\fboxsep}{1pt}% + \color{white}\fbox{% + \scalebox{\mscscalefactor}{\raisebox{\msc@totalheight}[\msc@totalheight][0pt]{\usebox{\mscbox}}}% + }% +}% +\message{)}% +}% +% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\MSC@settitle}[7]{% + % #1: diagram type (msc, mscdoc, hmsc) + % #2: llx + % #3: lly + % #4: urx + % #5: ury + % #6: justification (l, c, r) + % #7: typeset title + \setlength{\tmp@X}{#4 - #2 - 2\leftnamedist}% + \ifthenelse{\equal{#6}{l}}% + {% + \def\MSC@dosettitle{\parbox[t]{\tmp@X}{\raggedright #7}}% + }% + {\ifthenelse{\equal{#6}{c}}% + {% + \def\MSC@dosettitle{\parbox[t]{\tmp@X}{\centering #7}}% + }% + {\ifthenelse{\equal{#6}{r}}% + {% + \def\MSC@dosettitle{\parbox[t]{\tmp@X}{\raggedleft #7}}% + }% + {\msc@illegaltitleplacement{#6}}% + }% + }% + \setlength{\tmp@Y}{#5 - \topnamedist}% + \setlength{\tmp@Xb}{#2 + \leftnamedist}% + \rput[tl](\tmp@Xb,\tmp@Y){\MSC@dosettitle}% +} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% MSC documents +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \mscdockeyword is the keyword representation of msc +\def\mscdockeyword{mscdoc} +\def\mscdockeywordstyle#1{\textbf{#1}} +% +% This keyword can be changed by the \setmscdockeyword command (or by \renewcommand{\mscdockeyword}{...}): +\newcommand{\setmscdockeyword}[1]{\def\mscdockeyword{#1}} +\newcommand{\setmscdockeywordstyle}[1]{\def\mscdockeywordstyle{#1}}% + +\newcommand{\mscdoc@settitle}{% + \MSC@settitle{mscdoc}% + {\mscdoc@llx}% + {\mscdoc@lly}% + {\mscdoc@urx}% + {\mscdoc@ury}% + {\mscdoc@titlejustification}% + {\mscdockeywordstyle{\mscdockeyword}{} \mscdoc@title}% +} + +\newenvironment{mscdoc}[2][l]% +{% + \message{( \mscdockeyword: '#2'}% + \def\mscdoc@titlejustification{#1}% + \def\mscdoc@title{#2}% + \def\reference##1(##2,##3){% + \setlength{\tmp@X}{\mscdocreferencewidth}% + \setlength{\tmp@Y}{\mscdocreferenceheight}% + \def\txt{\vbox to \tmp@Y{\vss\hbox to \tmp@X{\hss{}##1\hss}\vss}}% + \rput(##2\mscunit,##3\mscunit){\psframebox[% + framearc=0.25,% + framesep=0pt,% + border=0pt% + ]{\txt}}}% + \def\separator##1{% + \psline[linestyle=dashed](\mscdoc@llx,##1)(\mscdoc@urx,##1) + }% + \def\mscdoc@sizespec(##1,##2)(##3,##4)% + {% + \def\mscdoc@llx{##1\mscunit}% + \def\mscdoc@lly{##2\mscunit}% + \def\mscdoc@urx{##3\mscunit}% + \def\mscdoc@ury{##4\mscunit}% +\begin{lrbox}{\mscbox}% + \begin{pspicture}(\mscdoc@llx,\mscdoc@lly)(\mscdoc@urx,\mscdoc@ury)% + \ifthenelse{\equal{\msc@grid}{yes}}{% + \psgrid[subgriddiv=1,griddots=10](\mscdoc@llx,\mscdoc@lly)(\mscdoc@urx,\mscdoc@ury)% + }{\relax}% + \ifthenelse{\equal{\msc@frame}{yes}}{% + \psframe(\mscdoc@llx,\mscdoc@lly)(\mscdoc@urx,\mscdoc@ury)% + }{\relax}% + \mscdoc@settitle% + }% + \mscdoc@sizespec% +}% +{% + \end{pspicture}% +\end{lrbox}% +{% DEBUG: use this \fbox stuf to check the bounding box + \setlength{\fboxrule}{0.01pt}% + \setlength{\fboxsep}{1pt}% + \color{white}\fbox{% + \usebox{\mscbox}% + }% +}% + \message{)}% +} + +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% HMSC +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\RequirePackage{pst-node} + + +\newcommand{\hmsckeyword}{hmsc} +\newcommand{\hmsckeywordstyle}[1]{\textbf{#1}} + +% This keyword can be changed by the \sethmsckeyword command (or by \renewcommand{\hmsckeyword}{...}): +\newcommand{\sethmsckeyword}[1]{\def\hmsckeyword{#1}} +\newcommand{\sethmsckeywordstyle}[1]{\def\hmsckeywordstyle{#1}}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\newif\if@ncsegline + + +% +% User command to draw a segmented line between two nodes (buggy). +% +% NOTE: this implementation is not complete yet. The optional arrows argument +% only makes sense for forward arrows (and even then in a limited way). +% usage: \ncsegline[settings]{arrows}{#1}[(x0,y0)...(xn,xy)]{#2} +% settings (optional): pstricks settings for lines +% arrows(optional): pstricks-style arrow defintions +% #1: start node +% (x0,y0)...(xn,yn) (optional): sequence of intermediate points +% #2: end node +\def\ncsegline{% + \@ifstar{\def\@nclinecommand{\ncline*}\@ncseglinei}{\def\@nclinecommand{\ncline}\@ncseglinei}% +} + +\def\ncseglinecheck@arrow#1#2{% + \ncseglinecheck@@arrow#2-\@nil + \if@ncsegline% +% \message{(arrow: `#2')}% + \edef\@ncseglinearrow{{#2}}% + \def\next{#1}% + \else% +% \message{(no arrow `#2')}% + \edef\@ncseglinearrow{{-}}% + \def\next{#1{#2}}% + \fi% + \next% +} + +\def\ncseglinecheck@@arrow#1-#2\@nil{% +\ifx\@nil#2\@nil\@ncseglinefalse\else\@ncseglinetrue\fi} + +\def\@ncseglinei{% + \@ifnextchar[{\@ncseglineReadSettings}{\def\@nclinesettings{[]}\ncseglinecheck@arrow{\@ncseglineii}}%] +} + +\def\@ncseglineReadSettings[#1]{% + \def\@nclinesettings{[#1]}% + \ncseglinecheck@arrow{\@ncseglineii}% +} + +\def\@ncseglineii#1{% + \def\@ncsegargA{#1}% + \@ifnextchar[{\@ncseglineiii}{\@ncseglineiv}% +} + +\def\@ncseglineiii[#1]#2{% + \@ncseglineA#1(\relax,\relax)% + \def\@ncsegargB{#2}% + \@ncseglinedraw% +} + +\def\@ncseglineiv#1{% + \def\@ncsegargB{#1}% + \@ncseglinedraw% +} + +\def\@ncseglinedraw{% + \edef\@ncseglineattrs{\@nclinesettings\@ncseglinearrow}% + \expandafter\@nclinecommand\@ncseglineattrs{\@ncsegargA}{\@ncsegargB}% +} + +\def\@ncseglineA(#1,#2){% + \ifx#1\relax% + \def\next{\relax}% + \else% +% \message{(line seg)}% + \pnode(#1,#2){#1#2}% + \expandafter\@nclinecommand\@nclinesettings{-}{\@ncsegargA}{#1#2}% + \edef\@ncsegargA{#1#2}% + \def\next{\@ncseglineA}% + \fi + \next% +} + +% User command to draw hmsc start symbols +% usage: \hmscstartsymbol{#1}(#2,#3) +% #1: nickname +% #2: x-coordinate +% #3: y-coordinate +% +% +% sin(pi/3) =~ 0.866025403784 +% +\def\hmscstartsymbol#1(#2,#3){% + %\message{(hmsc start symbol: #1)}% + \setlength{\tmp@Xa}{#2\mscunit}% + \setlength{\tmp@Ya}{#3\mscunit}% + \setlength{\tmp@Xb}{\tmp@Xa}\addtolength{\tmp@Xb}{-.5\hmscstartsymbolwidth}% + \setlength{\tmp@Xc}{\tmp@Xa}\addtolength{\tmp@Xc}{.5\hmscstartsymbolwidth}% + \setlength{\tmp@Yb}{\tmp@Ya}\addtolength{\tmp@Yb}{0.866025403784\hmscstartsymbolwidth}% + \pspolygon(\tmp@Xa,\tmp@Ya)(\tmp@Xb,\tmp@Yb)(\tmp@Xc,\tmp@Yb)% + \pnode(#2,#3){#1}% +} + + +% User command to draw hmsc end symbols +% usage: \hmscendsymbol{#1}(#2,#3) +% #1: nickname +% #2: x-coordinate +% #3: y-coordinate +% +% +% sin(pi/3) =~ 0.866025403784 +% +\def\hmscendsymbol#1(#2,#3){% + %\message{(hmsc end symbol: #1)}% + \setlength{\tmp@Xa}{#2\mscunit}% + \setlength{\tmp@Ya}{#3\mscunit}% + \setlength{\tmp@Xb}{\tmp@Xa}\addtolength{\tmp@Xb}{-.5\hmscstartsymbolwidth}% + \setlength{\tmp@Xc}{\tmp@Xa}\addtolength{\tmp@Xc}{.5\hmscstartsymbolwidth}% + \setlength{\tmp@Yb}{\tmp@Ya}\addtolength{\tmp@Yb}{-0.866025403784\hmscstartsymbolwidth}% + \pspolygon(\tmp@Xa,\tmp@Ya)(\tmp@Xb,\tmp@Yb)(\tmp@Xc,\tmp@Yb)% + \pnode(#2,#3){#1}% +} + +% User command to draw a hmsc condition +% usage: \hmsccondition{#1}{#2}(#3,#4) +% #1: nickname +% #2: text +% #3: x-coordinate +% #4: y-coordinate +\def\hmsccondition#1#2(#3,#4){% + \setlength{\tmp@X}{.5\hmscconditionwidth}% + \setlength{\tmp@Y}{.5\hmscconditionheight}% + \setlength{\tmp@Xa}{\tmp@X}\addtolength{\tmp@Xa}{.6\tmp@Y}% + \rput(#3\mscunit,#4\mscunit){% + \pspolygon(-\tmp@X,\tmp@Y)% + (\tmp@X,\tmp@Y)% + (\tmp@Xa,0)% + (\tmp@X,-\tmp@Y)% + (-\tmp@X,-\tmp@Y)% + (-\tmp@Xa,0)}% + \setlength{\tmp@X}{\hmscconditionwidth}% + \setlength{\tmp@Y}{\hmscconditionheight}% + \def\ctxt{\vbox to \tmp@Y{\vss\hbox to \tmp@X{\hss{}#2\hss}\vss}}% + \rput(#3\mscunit,#4\mscunit){\rnode{#1}{\psframebox[% + linestyle=none,% + linewidth=0pt,% + framesep=0pt,% + border=0pt% + ]{\ctxt}}}% +} + +% User command to draw a hmsc reference +% usage: \hmscreference{#1}{#2}(#3,#4) +% #1: nickname +% #2: text +% #3: x-coordinate +% #4: y-coordinate +\def\hmscreference#1#2(#3,#4){% + \setlength{\tmp@X}{\hmscreferencewidth}% + \setlength{\tmp@Y}{\hmscreferenceheight}% + \def\rtxt{\vbox to \tmp@Y{\vss\hbox to \tmp@X{\hss{}#2\hss}\vss}}% + \rput(#3\mscunit,#4\mscunit){\rnode{#1}{\psframebox[% + framearc=0.25,% + framesep=0pt,% + border=0pt% + ]{\rtxt}}}% +} + +% User command to draw hmsc connections +% usage: \hmscconnection{#1}(#2,#3) +% #1: nickname +% #2: x-coordinate +% #3: y-coordinate +\def\hmscconnection#1(#2,#3){% + \rput(#2,#3){\circlenode[framesep=0pt]{#1}{\rule{0pt}{2\hmscconnectionradius}}}% +} + + + +% User command to draw arrows between hmsc-objects +% Usage: \arrow{#1}[(x0,y0)...(xn,yn)]{#2} +% #1: start hmsc object +% (x0,y0)...(xn,yn) (optional): sequence of intermediate points +% #2: end hmsc object +\newcommand{\arrow}{ + \ncsegline{->}% +} + + + +% User environment to draw hmsc's +% Usage: \begin{hmsc}{#1}(llx,lly((urx,ury)...\end{hmsc} +% + + +\def\hmsc@settitle{% + \MSC@settitle{hmsc}% + {\hmsc@llx}% + {\hmsc@lly}% + {\hmsc@urx}% + {\hmsc@ury}% + {\hmsc@titlejustification}% + {\hmsckeywordstyle{\hmsckeyword}{} \hmsc@title}% +% \setlength{\tmp@X}{\hmsc@llx + \leftnamedist}% +% \setlength{\tmp@Y}{\hmsc@ury - \topnamedist}% +% \rput[tl](\tmp@X,\tmp@Y){% +% \hmsckeywordstyle{\hmsckeyword}{} \hmsc@title% +% }% +} + +\newenvironment{hmsc}[2][l] + {\message{( \hmsckeyword: '#2'}% + \def\hmsc@titlejustification{#1}% + \def\hmsc@title{#2}% + \hmsc@startenv}% + {%\setlength{\tmp@X}{\hmsc@llx}\addtolength{\tmp@X}{\leftnamedist}% + %\setlength{\tmp@Y}{\hmsc@ury}\addtolength{\tmp@Y}{-\topnamedist}% + %\rput[tl](\tmp@X,\tmp@Y){\raisebox{\depth}[\totalheight][0pt]{\hmsckeywordstyle{\hmsckeyword} \hmsc@name}}% + \hmsc@settitle% + \ifthenelse{\equal{\msc@frame}{yes}}{% + \psframe(\hmsc@llx,\hmsc@lly)(\hmsc@urx,\hmsc@ury)% + }{\relax}% + \end{pspicture}% +\end{lrbox}% +{% DEBUG: use this \fbox stuf to check the bounding box + \setlength{\fboxrule}{0.01pt}% + \setlength{\fboxsep}{1pt}% + \color{white}\fbox{% + \usebox{\mscbox}% + }% +}% + \message{)}}% +\def\hmsc@startenv(#1,#2)(#3,#4){% + \newcommand{\hmsc@llx}{#1\mscunit}% + \newcommand{\hmsc@lly}{#2\mscunit}% + \newcommand{\hmsc@urx}{#3\mscunit}% + \newcommand{\hmsc@ury}{#4\mscunit}% +\begin{lrbox}{\mscbox}% + \begin{pspicture}(\hmsc@llx,\hmsc@lly)(\hmsc@urx,\hmsc@ury)% + \ifthenelse{\equal{\msc@grid}{yes}}{% + \psgrid[subgriddiv=1,griddots=10](\hmsc@llx,\hmsc@lly)(\hmsc@urx,\hmsc@ury)% + }{\relax}% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Initialisation of the msc package +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \set@mscvalueslarge +\def\set@mscvalueslarge{% + \psset{linewidth=0.8pt} + % the lengths + \setlength{\actionheight}{0.75\mscunit} + \setlength{\actionwidth}{1.25\mscunit} + \setlength{\bottomfootdist}{1\mscunit} + \setlength{\msccommentdist}{1.5\mscunit} + \setlength{\conditionheight}{0.75\mscunit} + \setlength{\conditionoverlap}{0.6\mscunit} + \setlength{\envinstdist}{2.5\mscunit} + \setlength{\firstlevelheight}{0.75\mscunit} + \setlength{\hmscconditionheight}{0.8\mscunit} + \setlength{\hmscconditionwidth}{1.6\mscunit} + \setlength{\hmscconnectionradius}{0.06\mscunit} + \setlength{\hmscreferenceheight}{0.8\mscunit} + \setlength{\hmscreferencewidth}{1.6\mscunit} + \setlength{\hmscstartsymbolwidth}{0.85\mscunit} + \setlength{\inlineoverlap}{1.5\mscunit} + \setlength{\instbarwidth}{0pt} + \setlength{\instdist}{3\mscunit} + \setlength{\instfootheight}{0.25\mscunit} + \setlength{\instheadheight}{.6\mscunit} + \setlength{\instwidth}{1.75\mscunit} + \setlength{\labeldist}{1ex} + \setlength{\lastlevelheight}{0.5\mscunit} + \setlength{\leftnamedist}{0.3\mscunit} + \setlength{\levelheight}{.75\mscunit} + \setlength{\lostsymbolradius}{.15\mscunit} + \setlength{\markdist}{1\mscunit} + \setlength{\measuredist}{0.75\mscunit} + \setlength{\measuresymbolwidth}{.15\mscunit} + \setlength{\mscdocreferenceheight}{0.8\mscunit} + \setlength{\mscdocreferencewidth}{1.6\mscunit} + \setlength{\referenceoverlap}{1.5\mscunit} + \setlength{\regionbarwidth}{.5\mscunit} + \setlength{\selfmesswidth}{.75\mscunit} + \setlength{\stopwidth}{0.6\mscunit} + \setlength{\timerwidth}{0.4\mscunit} + \setlength{\topheaddist}{1.5\mscunit} + \setlength{\topnamedist}{.3\mscunit} + % some numeric parameters + \messarrowscale{2} +} +% +% +% \set@mscvaluesnormal +\def\set@mscvaluesnormal{% + \psset{linewidth=0.7pt} + % switch to a smaller font + \small% + % the lengths + \setlength{\actionheight}{0.6\mscunit} + \setlength{\actionwidth}{1.25\mscunit} + \setlength{\bottomfootdist}{0.7\mscunit} + \setlength{\msccommentdist}{1.1\mscunit} + \setlength{\conditionheight}{0.6\mscunit} + \setlength{\conditionoverlap}{0.5\mscunit} + \setlength{\envinstdist}{2\mscunit} + \setlength{\firstlevelheight}{0.6\mscunit} + \setlength{\hmscconditionheight}{0.7\mscunit} + \setlength{\hmscconditionwidth}{1.4\mscunit} + \setlength{\hmscconnectionradius}{0.05\mscunit} + \setlength{\hmscreferenceheight}{0.7\mscunit} + \setlength{\hmscreferencewidth}{1.4\mscunit} + \setlength{\hmscstartsymbolwidth}{0.7\mscunit} + \setlength{\inlineoverlap}{1\mscunit} + \setlength{\instbarwidth}{0pt} + \setlength{\instdist}{2.2\mscunit} + \setlength{\instfootheight}{0.2\mscunit} + \setlength{\instheadheight}{.55\mscunit} + \setlength{\instwidth}{1.6\mscunit} + \setlength{\labeldist}{1ex} + \setlength{\lastlevelheight}{0.4\mscunit} + \setlength{\leftnamedist}{0.2\mscunit} + \setlength{\levelheight}{.5\mscunit} + \setlength{\lostsymbolradius}{.12\mscunit} + \setlength{\markdist}{1\mscunit} + \setlength{\measuredist}{0.6\mscunit} + \setlength{\measuresymbolwidth}{.2\mscunit} + \setlength{\mscdocreferenceheight}{0.7\mscunit} + \setlength{\mscdocreferencewidth}{1.4\mscunit} + \setlength{\referenceoverlap}{1\mscunit} + \setlength{\regionbarwidth}{.4\mscunit} + \setlength{\selfmesswidth}{.6\mscunit} + \setlength{\stopwidth}{0.5\mscunit} + \setlength{\timerwidth}{0.3\mscunit} + \setlength{\topheaddist}{1.3\mscunit} + \setlength{\topnamedist}{.2\mscunit} + % some numeric parameters + \messarrowscale{1.5} +} +% +% \set@mscvaluessmall +\def\set@mscvaluessmall{% + \psset{linewidth=0.6pt} + % switch to a smaller font + \small% + % the lengths + \setlength{\actionheight}{0.5\mscunit} + \setlength{\actionwidth}{1.2\mscunit} + \setlength{\bottomfootdist}{0.5\mscunit} + \setlength{\msccommentdist}{0.75\mscunit} + \setlength{\conditionheight}{0.5\mscunit} + \setlength{\conditionoverlap}{0.4\mscunit} + \setlength{\envinstdist}{1.2\mscunit} + \setlength{\firstlevelheight}{0.4\mscunit} + \setlength{\hmscconditionheight}{0.6\mscunit} + \setlength{\hmscconditionwidth}{1.2\mscunit} + \setlength{\hmscconnectionradius}{0.04\mscunit} + \setlength{\hmscreferenceheight}{0.6\mscunit} + \setlength{\hmscreferencewidth}{1.2\mscunit} + \setlength{\hmscstartsymbolwidth}{0.4\mscunit} + \setlength{\inlineoverlap}{.75\mscunit} + \setlength{\instbarwidth}{0pt} + \setlength{\instdist}{1.5\mscunit} + \setlength{\instfootheight}{0.15\mscunit} + \setlength{\instheadheight}{0.5\mscunit} + \setlength{\instwidth}{1.2\mscunit} + \setlength{\labeldist}{0.8ex} + \setlength{\lastlevelheight}{0.3\mscunit} + \setlength{\leftnamedist}{0.1\mscunit} + \setlength{\levelheight}{0.4\mscunit} + \setlength{\lostsymbolradius}{.08\mscunit} + \setlength{\markdist}{1\mscunit} + \setlength{\measuredist}{0.4\mscunit} + \setlength{\measuresymbolwidth}{.25\mscunit} + \setlength{\mscdocreferenceheight}{0.6\mscunit} + \setlength{\mscdocreferencewidth}{1.2\mscunit} + \setlength{\referenceoverlap}{.75\mscunit} + \setlength{\regionbarwidth}{.2\mscunit} + \setlength{\selfmesswidth}{.4\mscunit} + \setlength{\stopwidth}{0.3\mscunit} + \setlength{\timerwidth}{0.2\mscunit} + \setlength{\topheaddist}{1.2\mscunit} + \setlength{\topnamedist}{.1\mscunit} + % some numeric parameters + \messarrowscale{1.2} +} +% \setmscvalues assigns compatible values to all msc-parameters +% Currently, three sets of values are supported: large, normal +% and small. +\def\setmscvalues#1{% + \ifthenelse{\equal{#1}{large}}{% + \set@mscvalueslarge}{% + \ifthenelse{\equal{#1}{normal}}{% + \set@mscvaluesnormal}{% + \ifthenelse{\equal{#1}{small}}{% + \set@mscvaluessmall}{% + \ifthenelse{\equal{#1}{measure}}{% + \set@mscvaluesmeasure}{% + \msc@unknownmscvalueserr{#1}}}}}% +} +% +% initialisation of the msc-parameters +\setmscvalues{normal} +\setfootcolor{black} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Error and help messages +% We use the standard LaTeX2e facilities to generate error and help +% messages (for more info, see file lterror.dtx of LaTeX2e distribution). +% +% +% nickname already defined +\gdef\msc@nicknamedefinederr#1{% + \PackageError{msc}{% error message + nickname #1 already defined}{% help text + You tried to use the nickname '#1' for a new\MessageBreak + msc object (instance, reference, inline expression, etc.),\MessageBreak + but the nickname is already assigned to another msc object.\MessageBreak + press <enter> to continue (the new msc object will be ignored).}% +} +% +% no such msc instance error +\gdef\msc@instundefinederr#1{% + \PackageError{msc}{% error message + undefined msc instance: #1}{% help text + You used '#1' as an msc instance nickname, but\MessageBreak + there is no msc instance with that nickname.}% +} +% +% unknown linestyle error +\gdef\msc@unknownlinestyleerr#1{% + \PackageError{msc}{% error message + unknown linestyle: #1}{% help text + Known msc linestyles are "solid", "dashed", and "dotted".\MessageBreak + You used '#1'.}% +} +% +% unknown region style error +\gdef\msc@unknownregionstyleerr#1{% + \PackageError{msc}{% error message + unknown region style: #1}{% help text + Known msc region styles are "normal", "coregion", "suspension", and "activation".\MessageBreak + You used '#1'.}% +} +% +% unknown self message label position error +\gdef\msc@unknownselfmessposerr#1{% + \PackageError{msc}{% error message + unknown position for self message: #1}{% help text + Known positions are "l" (left), "r" (right).\MessageBreak + You used '#1'.}% +} +% +% unknown self message label position error +\gdef\msc@unknowntimerposerr#1{% + \PackageError{msc}{% error message + unknown timer position: #1}{% help text + Known timer positions are "l" (left), "r" (right).\MessageBreak + You used '#1'.}% +} +% +% unknown self message label position error +\gdef\msc@unknownmscvalueserr#1{% + \PackageError{msc}{% error message + unknown set of msc-values: #1}{% help text + Known sets of msc-values are "normal" and "small".\MessageBreak + You used '#1'.}% +} +% +% no such msc reference error +\gdef\msc@refundefinederr#1{% + \PackageError{msc}{% error message + undefined reference: #1}{% help text + You used '#1' as a reference nickname, but\MessageBreak + there is no reference with that nickname.}% +} +% +% no such msc inline error +\gdef\msc@inlundefinederr#1{% + \PackageError{msc}{% error message + undefined inline expression: #1}{% help text + You used '#1' as a inline expression nickname, but\MessageBreak + there is no inline expression with that nickname.}% +} +% +% inline first right from last error +\gdef\msc@inlfirstlasterror#1#2#3{% + \PackageError{msc}{% error message + first instance right from final instance\MessageBreak in inline expression #1}{% help text + In the definition of inline expression '#1', you probably switched\MessageBreak + the first msc instance, '#2', and the final msc instance, '#3',\MessageBreak + since the first is located right from the final.}% +} +% +% reference first rightt from last error +\gdef\msc@reffirstlasterror#1#2#3{% + \PackageError{msc}{% error message + first instance right from final instance\MessageBreak in reference #1}{% help text + In the definition of msc reference '#1', you probably switched\MessageBreak + the first msc instance, '#2', and the final msc instance, '#3',\MessageBreak + since the first is located right from the final.}% +} +% +\gdef\msc@illegalmarkplacement#1{% + \PackageError{msc}{% + illegal mark placement specifier: #1}{% help text + The four mark placement specifiers are:\MessageBreak + tl (top-left)\MessageBreak + bl (bottom-left)\MessageBreak + tr (top-right)\MessageBreak + br (bottom-right)} +} +\gdef\msc@illegalmesslabelpositionerr#1{% + \PackageError{msc}{% + illegal label position specifier: #1}{% help text + Valid label position specifiers are:\MessageBreak + t (top)\MessageBreak + b (bottom)} +} +\gdef\msc@illegalselfmesspositionerr#1{% + \PackageError{msc}{% + illegal label position: #1}{% help text + Valid label positions are:\MessageBreak + t (top)\MessageBreak + b (bottom)\MessageBreak + l (left)\MessageBreak + r (right)} +} +\gdef\msc@illegallostfoundlabelpositionerr#1{% + \PackageError{msc}{% + in lost/found message: illegal label position: #1}{% help text + Valid label position are:\MessageBreak + t (top)\MessageBreak + b (bottom)} +} +%################################################################################ +% +\gdef\msc@illegaltitleplacement#1{% + \PackageError{msc}{% + illegal title placement specifier: #1}{% help text + Valid title placement specifiers are:\MessageBreak + l (left)\MessageBreak + c (center)\MessageBreak + r (right)} +} +%################################################################################ +\gdef\hmsc@nicknamedefinederr#1{% + \PackageError{msc}{% error message + nickname #1 already defined}{% help text + You tried to use the nickname '#1' for a new\MessageBreak + hmsc object (startsymbol, endsymbol, reference, etc.),\MessageBreak + but the nickname is already assigned to another hmsc object.\MessageBreak + press <enter> to continue (the new hmsc object will be ignored).}% +} +% no such msc hmsc object error +\gdef\hmsc@objectundefinederr#1{% + \PackageError{msc}{% error message + undefined hmsc object: #1}{% help text + You used '#1' as an hmsc object nickname, but\MessageBreak + there is no hmsc object with that nickname.}% +}% +% hmsc unknown connection type +\gdef\hmsc@unknownconnectiontypeerror#1{% + \PackageError{msc}{% error message + Unknown HMSC connection type: #1}{% help text + Known HMSC connection types are straight, rounded, and curved.}% +} +% +% hmsc missing y coordinate in arrow specification +\gdef\hmsc@missingycoord#1#2{% + \PackageError{msc}{% error message + Missing Y coordinate in arrow specification. You typed:\MessageBreak + [#2]\MessageBreak + which is parsed as the incomplete list of points:\MessageBreak + #1\MessageBreak + Remove the final X coordinate or add an Y coordinate}{% + The points specifying an HMSC arrow should be given as a comma separated\MessageBreak + list of X, Y coordinates. Furthermore, each X coordinate should\MessageBreak + be followed by a Y coordinate.}% +} +% remarks +% +% Issuing pstricks drawing-commands inside a TeX-group in a pspicture environment +% can result in ill-positioned objects. +% +% messages from/to the right environment should be defined after the last +% instance is declared with \declinst + |