From 2afee5e322fb0dfc2764c270803bc6381b65636e Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sat, 14 May 2022 03:00:57 +0000 Subject: CTAN sync 202205140300 --- macros/latex/contrib/msc/msc.sty | 5855 +++++++++++++++++++------------------- 1 file changed, 2882 insertions(+), 2973 deletions(-) (limited to 'macros/latex/contrib/msc/msc.sty') diff --git a/macros/latex/contrib/msc/msc.sty b/macros/latex/contrib/msc/msc.sty index 944e133ed9..889bb9a3a0 100644 --- a/macros/latex/contrib/msc/msc.sty +++ b/macros/latex/contrib/msc/msc.sty @@ -1,8 +1,7 @@ %% MSC Macro Package %% msc.sty -%% June 2, 2008 %% -%% Copyright 2008 V. Bos, T. van Deursen, and S. Mauw +%% Copyright 2022 V. Bos, T. van Deursen, P. Kordy, and S. Mauw % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 @@ -13,2966 +12,2964 @@ % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. -% -% The Current Maintainer of this work is T. van Deursen. % -% This program consists of the files +% The Current Maintainer of this work is P. Kordy +% +% This program consists of the files % msc.sty % manual.tex -% manual.pdf -% refman.tex -% refman.pdf +% manual_macros.tex % biblio.bib -% maintenance.tex -% maintenance.pdf % README % COPYRIGHT -% % Contact address: -% Ton van Deursen -% Universit\'e du Luxembourg -% Facult\'e des Sciences, de la Technologie et de la Communication -% 6, rue Richard Coudenhove-Kalergi -% L-1359 Luxembourg -% Email: ton.vandeursen@uni.lu -% Updates via: http://satoss.uni.lu/mscpackage/ -% - -\def\mscdate{2008/06/02}% update this whenever this file changes -\def\mscversion{1.16}% update this whenever a new version is ready -\NeedsTeXFormat{LaTeX2e}% +% Reynaldo Gil Pons +% Université du Luxembourg +% Maison du Nombre +% 6 Av. de la Fonte +% L-4364 Esch-sur-Alzette +% Email: reynaldo.gilpons@uni.lu +% Website: http://satoss.uni.lu/mscpackage/ + +\def\mscdate{2022/05/13}% update this whenever this file changes +\def\mscversion{2.00}% update this whenever a new version is ready +\NeedsTeXFormat{LaTeX2e}[1999/12/01] \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}% +\RequirePackage{tikz,xstring,calc} +\usetikzlibrary{ + positioning, + fit, + calc, + arrows, + decorations.markings, + shapes.misc, + shapes.geometric, + shapes.symbols +} +\pgfdeclarelayer{background} %background for drawing grid +\pgfsetlayers{background,main} + + +% {string}{target1}{target2}{code for match}{code for no match} +\newcommand*{\msc@StrEqEither}[5]{ + \IfEqCase{#1}{{#2}{#4}{#3}{#4}}[#5] +} +\newcommand*{\msc@caseFiveEither}[8]{ + \IfEqCase{#1}{{#2}{#7}{#3}{#7}{#4}{#7}{#5}{#7}{#6}{#7}}[#8] +} +%\newlength{\msc@textheight} +%\newlength{\msc@textdepth} +%\newlength{\msc@textwidth} +\newsavebox{\msc@box} +\newcommand{\msc@savebox}[1]{ + \savebox{\msc@box}{\pgfinterruptpicture#1\endpgfinterruptpicture} +} +% +%% \tracingmacros=2 \tracingcommands=2 %used for debugging +% "msc" is a family +\pgfkeys{/msc/.is family} +% set up a search path: +\pgfkeys{/msc/.search also={/tikz}} +% \pgfkeys{/msc/message/.search also={/msc}} +\newif\ifmsc@isstar +\newif\ifmsc@ismessreplay +\def\mscset{\pgfqkeys{/msc}} +\def\mscget#1{\pgfkeysvalueof{/msc/#1}} +% * Arrow * +\pgfarrowsdeclare{mscarrow}{mscarrow} +{ + \pgfmathparse{\pgfgetarrowoptions{mscarrow}}% + \ifpgfmathunitsdeclared% + \pgfmathparse{\pgfmathresult pt}% + \else% + \pgfmathparse{\pgfmathresult*\pgflinewidth}% + \fi% + \let\thickness=\pgfmathresult +% \edef\msc@thickness=\pgfmathresult + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgfmathresult pt + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgfutil@tempdimb-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfarrowsleftextend{-3\pgfutil@tempdima} + \pgfarrowsrightextend{+5\pgfutil@tempdima} +} +{ + \pgfmathparse{\pgfgetarrowoptions{mscarrow}}% + \ifpgfmathunitsdeclared% + \pgfmathparse{\pgfmathresult pt}% + \else% + \pgfmathparse{\pgfmathresult*\pgflinewidth}% + \fi% + \let\thickness=\pgfmathresult + \pgfsetlinewidth{\thickness pt} + \pgfutil@tempdima=0.28pt% + \pgfutil@tempdimb=\pgflinewidth% + \ifdim\pgfinnerlinewidth>0pt% + \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}% + \fi% + \advance\pgfutil@tempdima by.3\pgfutil@tempdimb% + \pgfpathmoveto{\pgfqpoint{5\pgfutil@tempdima}{0pt}} + \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{4\pgfutil@tempdima}} + \pgfpathlineto{\pgfpointorigin} + \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{-4\pgfutil@tempdima}} + \pgfusepathqfill +} +\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{\gatesymbolradius} % radius of the gate symbol +\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 and mscdoc reference symbol +\newlength{\hmscreferencewidth} % width of hmsc and mscdoc reference symbol +\newlength{\hmscstartsymbolwidth} % width of hmsc start/end 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} % the width of the coregion start and end symbol +\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 +\mscset{% + %mscdoc keys + /msc/mscdoc margin/.code={ + \mscset{ + north mscdoc margin/.initial=#1, + south mscdoc margin/.initial=#1, + east mscdoc margin/.initial=#1, + west mscdoc margin/.initial=#1 + } + }, + top mscdoc margin/.style={north mscdoc margin=#1}, + bottom mscdoc margin/.style={south mscdoc margin=#1}, + left mscdoc margin/.style={west mscdoc margin=#1}, + right mscdoc margin/.style={east mscdoc margin=#1}, + /msc/mscdoc margin=0.5cm, + /msc/mscdoc keyword/.initial=mscdoc, + %hmsc keys + /msc/hmsc keyword/.initial=hmsc, + /msc/hmsc margin/.code={ + \mscset{ + north hmsc margin/.initial=#1, + south hmsc margin/.initial=#1, + east hmsc margin/.initial=#1, + west hmsc margin/.initial=#1 + } + }, + top hmsc margin/.style={north hmsc margin=#1}, + bottom hmsc margin/.style={south hmsc margin=#1}, + left hmsc margin/.style={west hmsc margin=#1}, + right hmsc margin/.style={east hmsc margin=#1}, + /msc/hmsc margin=0.5cm, + %msc keys + /msc/msc keyword/.initial=msc, + /msc/inline overlap/.code={ + \mscset{ + right inline overlap/.initial=#1, + left inline overlap/.initial=#1 + } + }, + environment distance/.code={ + \mscset{ + right environment distance/.initial=#1, + left environment distance/.initial=#1 + } + }, % distance between environments and the % first level + /msc/reference overlap/.code={ + \mscset{ + right reference overlap/.initial=#1, + left reference overlap/.initial=#1 + } + }, + /msc/message options/.is family, %options for message + /msc/action options/.is family, %options for action and naction + /msc/msccomment options/.is family, %options for message comments +% Default value keys + /msc/line width/.initial=0.7pt, + side/.initial=left, %side on which to draw self message + position/.initial=above, %how to draw mscmark - possible %values:above mid below + /msc/side/.belongs to family=/msc/message options, + /msc/side/.belongs to family=/msc/msccomment options, + /msc/msccomment distance/.belongs to family=/msc/msccomment options, + /msc/offset/.belongs to family=/msc/msccomment options, + /msc/offset/.belongs to family=/msc/message options, + /msc/timer width/.belongs to family=/msc/msccomment options, + /msc/self message width/.belongs to family=/msc/msccomment options, + /msc/label distance/.belongs to family=/msc/msccomment options, + /msc/label position/.initial=above, %position of label in self message + /msc/label position/.belongs to family=/msc/message options, + /msc/level shift/.initial=0, %level shift in message + /msc/offset/.initial=2, %level shift in timers/self message etc + /msc/dummy text/.initial={ }, %text used for determining the size of dummy node + /msc/level shift/.belongs to family=/msc/message options, + /msc/pos/.initial=0.5, %placement of label in message + /msc/pos/.belongs to family=/msc/message options, + level offset/.initial=1, %level shift in nextlevel + level offset/.default=1, + /tikz/font=\small, + /msc/draw frame/.initial=, %color of the frame - if "none" we do not draw - "empty" uses last color usually black + /msc/draw frame/.default=, + /msc/draw head/.initial=, %color of the instance head + /msc/draw head/.default=, + /msc/draw foot/.initial=, %color of the instance foot + /msc/draw foot/.default=, + /msc/draw grid/.initial=none, %style to draw help lines - if empty we do + %not draw, other possible values are "none", "grid" or "color grid" + /msc/draw grid/.default=grid, + /msc/draw color grid/.style={draw grid=color grid}, +% the lengths + fat/.initial=normal, + fat/.default=fat, + %sizes + /tikz/font=\normalsize, % use normal size of font + action height/.initial=\the\actionheight, % height of action symbols + action height/.code={\setlength{\actionheight}{#1}}, + action width/.initial=\the\actionwidth, % width of action symbol + action width/.code={\setlength{\actionwidth}{#1}}, + foot distance/.initial=\the\bottomfootdist, % distance between bottom of foot symbol and frame + foot distance/.code={\setlength{\bottomfootdist}{#1}}, + msccomment distance/.initial=\the\msccommentdist, % distance of comment to its instance + msccomment distance/.code={\setlength{\msccommentdist}{#1}}, % distance of comment to its instance + condition height/.initial=\the\conditionheight, % height of condition symbols + condition height/.code={\setlength{\conditionheight}{#1}}, % height of condition symbols + condition overlap/.initial=\the\conditionoverlap, % overlap of condition symbol + condition overlap/.code={\setlength{\conditionoverlap}{#1}}, % overlap of condition symbol + first level height/.initial=\the\firstlevelheight, % height of level just below head symbols + first level height/.code={\setlength{\firstlevelheight}{#1}}, + gate symbol radius/.initial=\the\gatesymbolradius, % radius of the gate symbol + gate symbol radius/.code={\setlength{\gatesymbolradius}{#1}}, + hmsc condition height/.initial=\the\hmscconditionheight, % height of hmsc condition symbol + hmsc condition height/.code={\setlength{\hmscconditionheight}{#1}}, + hmsc condition width/.initial=\the\hmscconditionwidth, % width of hmsc condition symbol + hmsc condition width/.code={\setlength{\hmscconditionwidth}{#1}}, + hmsc connection radius/.initial=\the\hmscconnectionradius, % radius of hmsc connection symbols + hmsc connection radius/.code={\setlength{\hmscconnectionradius}{#1}}, + reference height/.initial=\the\hmscreferenceheight, % height of hmsc and mscdoc reference symbol + reference height/.code={\setlength{\hmscreferenceheight}{#1}}, + reference width/.initial=\the\hmscreferencewidth, % width of hmsc and mscdoc reference symbol + reference width/.code={\setlength{\hmscreferencewidth}{#1}}, % width of hmsc and mscdoc reference symbol + hmsc symbol width/.initial=\the\hmscstartsymbolwidth, % width of hmsc start/end symbol + hmsc symbol width/.code={\setlength{\hmscstartsymbolwidth}{#1}}, % width of hmsc start/end symbol + instance distance/.initial=\the\instdist, % distance between (vertical) instance lines + instance distance/.code={\setlength{\instdist}{#1}}, + foot height/.initial=\the\instfootheight, % height of foot symbols + foot height/.code={\setlength{\instfootheight}{#1}}, + head height/.initial=\the\instheadheight, % height of head symbols + head height/.code={\setlength{\instheadheight}{#1}}, + instance width/.initial=\the\instwidth, % width of header and foot symbols + instance width/.code={\setlength{\instwidth}{#1}}, + label distance/.initial=\the\labeldist, % distance between labels and message lines or head symbol boxes + label distance/.code={\setlength{\labeldist}{#1}}, + last level height/.initial=\the\lastlevelheight, % height of level just above foot symbols + last level height/.code={\setlength{\lastlevelheight}{#1}}, + title distance/.initial=\the\leftnamedist, % distance between left of frame and (top of) msc title + title distance/.code={\setlength{\leftnamedist}{#1}}, + level height/.initial=\the\levelheight, % height of a level + level height/.code={\setlength{\levelheight}{#1}}, + lost symbol radius/.initial=\the\lostsymbolradius, % radius of the lost and found symbols + lost symbol radius/.code={\setlength{\lostsymbolradius}{#1}}, + mark distance/.initial=\the\markdist, % distance between mark and its instance + mark distance/.code={\setlength{\markdist}{#1}}, + measure distance/.initial=\the\measuredist, % user definable length for horizontal measure distance + measure distance/.code={\setlength{\measuredist}{#1}}, + measure symbol width/.initial=\the\measuresymbolwidth, % width of measure symbols + measure symbol width/.code={\setlength{\measuresymbolwidth}{#1}}, +% reference overlap/.initial=\the\referenceoverlap, % overlap of reference symbol +% reference overlap/.code={\setlength{\referenceoverlap}{#1}}, + region width/.initial=\the\regionbarwidth, % the width of the coregion start and end symbol + region width/.code={\setlength{\regionbarwidth}{#1}}, +% region width/.initial=0.4cm, % the width of the activation, suspension and coregion rectangle + self message width/.initial=\the\selfmesswidth, % length of horizontal arms of self messages + self message width/.code={\setlength{\selfmesswidth}{#1}}, + stop width/.initial=\the\stopwidth, % width of the stop symbol + stop width/.code={\setlength{\stopwidth}{#1}}, + timer width/.initial=\the\timerwidth, % width of the timer symbols + timer width/.code={\setlength{\timerwidth}{#1}}, + head top distance/.initial=\the\topheaddist, % distance between top of head symbols and frame + head top distance/.code={\setlength{\topheaddist}{#1}}, + title top distance/.initial=\the\topnamedist, % distance between top of frame and (top of) msc title + title top distance/.code={\setlength{\topnamedist}{#1}}, + instance end/.initial=stop, % type of ending for the instance foot (foot or stop) - changed to follow ITU-T Z.120 + title position/.initial=left, % justification of the title: left, right or center + arrow scale/.initial=1.5, % scale for the + % arrows + msc scale/.initial=1, % sets the scale factor + msc scale/.code={ % that scales everynthing including text but one must be + \pgfutil@ifundefined{msc@tikzstarted}{\relax}{ % careful with rotation transformations + \mscset{ + /tikz/scale=#1, + /tikz/every node/.style={scale=#1}} + } + \mscset{msc scale/.initial=#1} + }, +%Styles + every instance head/.style={}, % style applied to all instance heads + every instance foot/.style={}, % style applied to all instance feet + every instance line/.style={}, % style applied to all instance lines + every message/.style={}, % style applied to all message arrows + every msccomment/.style={}, % style applied to all msccomments + every mscmark/.style={}, % style applied to all mscmarks + every action/.style={}, % style applied to all actions and nactions + every action node/.style={}, % style applied to all actions and nactions nodes + every region/.style={}, % style applied to all regions + every coregion/.style={}, % style applied to all coregions + every suspension/.style={}, % style applied to all suspension regions + every activation/.style={}, % style applied to all activation regions + every timer/.style={}, % style applied to simple timers + every measure/.style={}, % style applied to all measures + every lostfound/.style={}, % style applied to all lost and found messages + every condition/.style={}, % style applied to all conditions + every order/.style={}, % style applied to all orders + every reference/.style={}, % style applied to all references + every inline/.style={}, % style applied to all inline expressions + large values/.style={% + /tikz/font=\normalsize, + /tikz/line width=0.8pt, + /msc/line width=0.8pt, + action height=0.75cm, + /msc/action height/.belongs to family=/msc/action options, + action width=1.25cm, + /msc/action width/.belongs to family=/msc/action options, + foot distance=1cm, + msccomment distance=1.5cm, + condition height=0.75cm, + condition overlap=0.6cm, + environment distance=2.5cm, + first level height=0.75cm, + gate symbol radius=0.5mm, + hmsc condition height=0.8cm, + hmsc condition width=1.6cm, + hmsc connection radius=0.06cm, + reference height=0.8cm, + reference width=1.6cm, + hmsc symbol width=0.85cm, + inline overlap=1.5cm, + instance distance=1.25cm, + foot height=0.25cm, + head height=0.6cm, + instance width=1.75cm, + label distance=1ex, + last level height=0.5cm, + title distance=0.3cm, + level height=0.75cm, + lost symbol radius=0.15cm, + mark distance=1cm, + measure distance=0.75cm, + measure symbol width=0.25cm, + reference overlap=1.5cm, + region width=0.5cm, + self message width=0.75cm, + stop width=0.6cm, + timer width=0.4cm, + head top distance=1.5cm, + title top distance=0.3cm, + arrow scale=2 + }, + normal values/.style={% +% /tikz/font=\small,% + /tikz/line width=0.7pt, + /msc/line width=0.7pt, + action height=0.6cm, + action width=1.25cm, + foot distance=0.7cm, + msccomment distance=1.1cm, + condition height=0.6cm, + condition overlap=0.5cm, + environment distance=2cm, + first level height=0.6cm, + gate symbol radius=0.5mm, + hmsc condition height=0.7cm, + hmsc condition width=1.4cm, + hmsc connection radius=0.05cm, + reference height=0.7cm, + reference width=1.4cm, + hmsc symbol width=0.7cm, + inline overlap=1cm, + instance distance=0.6cm, + foot height=0.2cm, + head height=0.55cm, + instance width=1.6cm, + label distance=1ex, + last level height=0.4cm, + title distance=0.2cm, + level height=0.5cm, + lost symbol radius=0.12cm, + mark distance=1cm, + measure distance=0.6cm, + measure symbol width=0.2cm, + reference overlap=1cm, + region width=0.4cm, + self message width=0.6cm, + stop width=0.5cm, + timer width=0.3cm, + head top distance=1.3cm, + title top distance=0.2cm, + arrow scale=1.5 + }, + small values/.style={% + /tikz/font=\small,% + /tikz/line width=0.6pt, + /msc/line width=0.6pt, + action height=0.5cm, + action width=1.2cm, + foot distance=0.5cm, + msccomment distance=0.75cm, + condition height=0.5cm, + condition overlap=0.4cm, + environment distance=1.2cm, + first level height=0.4cm, + gate symbol radius=0.5mm, + hmsc condition height=0.6cm, + hmsc condition width=1.2cm, + hmsc connection radius=0.04cm, + reference height=0.6cm, + reference width=1.2cm, + hmsc symbol width=0.4cm, + inline overlap=0.75cm, + instance distance=0.3cm, + foot height=0.15cm, + head height=0.5cm, + instance width=1.2cm, + label distance=0.8ex, + last level height=0.3cm, + title distance=0.1cm, + level height=0.4cm, + lost symbol radius=0.08cm, + mark distance=0.4cm, + measure distance=0.4cm, + measure symbol width=0.15cm, + reference overlap=0.75cm, + region width=0.2cm, + self message width=0.4cm, + stop width=0.3cm, + timer width=0.2cm, + head top distance=1.2cm, + title top distance=0.1cm, + arrow scale=1.2 + }, + /msc/start symbol/.style={draw,/tikz/line width=\mscget{line width}, + inner sep=0, + isosceles triangle,isosceles triangle apex angle=60, + shape border rotate=-90,minimum width=\mscget{hmsc symbol width}}, + /msc/end symbol/.style={start symbol,shape border rotate=90}, +%style to %draw hmsc condition + /msc/condition/.style={draw,/tikz/line width=\mscget{line width}, + minimum width=\mscget{hmsc condition width}, + minimum height=\mscget{hmsc condition height}, + inner sep=0pt, + signal pointer angle=120, + signal to=east and west, + signal}, + /msc/connection/.style={draw,/tikz/line width=\mscget{line width}, + minimum width=2*(\mscget{hmsc connection radius}) + \mscget{line width}, + circle + }, + /msc/reference/.style={draw,/tikz/line width=\mscget{line width}, + minimum width=\mscget{reference width}, + minimum height=\mscget{reference height}, + inner sep=2pt, + rounded corners=0.125cm, + rectangle, + }, + mscdash/.style={% + dash pattern=on 4pt off 4pt + }, + suspension dash/.style={% + dash pattern=on 7pt off 7pt, + dash phase=3.5pt + }, + settimer style/.style={% + /tikz/line width=\mscget{line width}, draw, + to path={-- ++(60:#1) -- ++(-#1,0) -- ++(-60:2*#1) -- ++(-#1,0) -- ++(60:#1) -- (\tikztotarget)} + }, + timeout style/.style={% + settimer style={#1}, arrow style + }, + stoptimer style/.style={% + /tikz/line width=\mscget{line width}, draw, + to path={ ++(0.5*#1,0.5*#1) -- ++(-#1,-#1) ++(0,#1) -- ++(#1,-#1) ++(-0.5*#1,0.5*#1) -- (\tikztotarget)} + }, + set mscarrow thickness/.code={ + \pgfsetarrowoptions{mscarrow}{#1}}, + arrow style/.default=\mscget{arrow scale}*\mscget{line width}, + arrow style/.style={set mscarrow thickness=#1, + shorten >=\mscget{line width}/2, + -mscarrow + }, + instance head/.style={% + rectangle, + text height=1.5ex,% + inner sep=2pt, +% text width=\mscget{instance width}, text centered,%uncomment to get old behaviour +% transform shape, + /tikz/line width=\mscget{line width}, + minimum height=\mscget{head height},% + minimum width=\mscget{instance width},% + label={[text height=1.5ex,text depth=0ex, + inner sep=0pt, /tikz/label distance=\mscget{label + distance}-\mscget{line width}-0.1ex]above:#1}% + }, + replay/.style={% + /tikz/line width=\mscget{line width}, + line cap=butt, + mscdash + }, + msccomment/.style={% + /tikz/line width=\mscget{line width}, + line cap=round, + }, + msccomment line/.style={% + mscdash + }, + message/.style={% + /tikz/line width=\mscget{line width}, + arrow style, + line cap=round, + }, + %action/.style={% + %/tikz/line width=\mscget{line width}, + %line cap=round, + %}, + instance line/.style={% + /tikz/line width=\mscget{line width}, + draw,%orange +% line cap=round + }, + message loop/.default=\mscget{self message width}, + message loop/.style={% + to path={-- ++(#1,0) coordinate (msc@somepoint) -- (msc@somepoint |- + \tikztotarget) \tikztonodes -- (\tikztotarget)} + }, + order loop/.default=\mscget{self message width}, + order loop/.style={% + set mscarrow thickness=\mscget{arrow scale}*\mscget{line width}, + decoration={markings, mark=at position \mscget{pos} with {\arrow{mscarrow}}}, + /tikz/line width=\mscget{line width},postaction={decorate}, + line cap=round, + mscdash, + to path={-- ++(#1,0) coordinate (msc@somepoint) -- (msc@somepoint |- + \tikztotarget) \tikztonodes -- (\tikztotarget)} + }, + order/.style={% + set mscarrow thickness=\mscget{arrow scale}*\mscget{line width}, + decoration={markings, mark=at position \mscget{pos} with {\arrow{mscarrow}}}, + /tikz/line width=\mscget{line width},postaction={decorate}, + line cap=round, + mscdash, + }, + settimeout style/.default={\mscget{self message width}}{\mscget{timer width}}, + settimeout style/.style 2 args={/msc, + /tikz/line width=\mscget{line width}, draw, arrow style, + to path={-- ++(#1,0) coordinate (msc@somepoint) -- ++(60:#2) -- + ++(-#2,0)--++(-60:2*#2) coordinate (msc@somepoin) -- ++(-#2,0) --(msc@somepoint) + ($ (msc@somepoint)!0.866*#2!(\tikztotarget-|msc@somepoint) $) -- + (\tikztotarget-|msc@somepoint) -> (\tikztotarget) + } + }, + setstoptimer style/.default={\mscget{self message width}}{\mscget{timer width}}, + setstoptimer style/.style 2 args={/msc, + /tikz/line width=\mscget{line width}, draw, + to path={-- ++(#1,0) coordinate (msc@somepoint) -- ++(60:#2) -- + ++(-#2,0)--++(-60:2*#2) coordinate (msc@somepoin) -- ++(-#2,0) --(msc@somepoint) + ($ (msc@somepoint)!0.866*#2!(\tikztotarget-|msc@somepoint) $) -- + (\tikztotarget-|msc@somepoint) ++(0.5*#2,0.5*#2) -- ++(-#2,-#2) + ++(0,#2) -- ++(#2,-#2) ++(-0.5*#2,0.5*#2) -- + (\tikztotarget) + }}, + measure style/.default={\mscget{measure distance}}{\mscget{measure symbol width}}, + measure style/.style 2 args={% + /tikz/line width=\mscget{line width}, mscdash, + to path={-- ++(#1,0) coordinate (a) + ($ (a)!0.866*#2!(\tikztotarget-|a)$) -- ($(\tikztotarget-|a) !0.866*#2!(a) $) + (a|-\tikztotarget) \tikztonodes coordinate (b) -- (\tikztotarget) + \pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];} + (a)--($ (a)!#2!30:(\tikztotarget-|a)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a) + (b)--($ (b)!#2!30:(a)$) coordinate (b1)--($ (b1)!#2!60:(b)$) --cycle(b) + \pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];} + (\tikztotarget) + }}, + measure* style/.default={\mscget{measure distance}}{\mscget{measure symbol width}}, + measure* style/.style 2 args={% + /tikz/line width=\mscget{line width}, mscdash, + to path={ + -- ++(#1,0) coordinate (a)-- (\tikztotarget-|a) coordinate (b)\tikztonodes + -- (\tikztotarget) + \pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];} + (a)--($ (a)!#2!210:(b)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a) + (b)--($ (b)!#2!210:(a)$) coordinate (b1)--($ (b1)!#2!60:(b)$) --cycle(b) + \pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];} + (\tikztotarget) + }}, + measurestart style/.default={\mscget{measure distance}}{\mscget{measure symbol width}}, + measurestart style/.style 2 args={% + /tikz/line width=\mscget{line width}, mscdash, + to path={ + -- ++(#1,0) coordinate (a) + ($ (a)!0.866*#2!(\tikztotarget-|a)$)-- ($(\tikztotarget-|a)! 0.5*#2!(a) $) \tikztonodes + (\tikztotarget -| a) coordinate (b) + \pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];} + (a)--($ (a)!#2!30:(\tikztotarget-|a)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a) + (b) circle (0.5*#2) + \pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];} + (\tikztotarget) + }}, + measurestart* style/.default={\mscget{measure distance}}{\mscget{measure symbol width}}, + measurestart* style/.style 2 args={% + /tikz/line width=\mscget{line width}, mscdash, + to path={ + -- ++(#1,0) coordinate (a) -- ($(\tikztotarget-|a)! 0.5*#2!(a) $) \tikztonodes + (\tikztotarget -| a) coordinate (b) + \pgfextra{ \path[draw,/msc/mscdash,/tikz/line width=\mscget{line width}];} + (a)--($ (a)!#2!210:(b)$) coordinate (a1)--($ (a1)!#2!60:(a)$) --cycle(a) + (b) circle (0.5*#2) + \pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];} + (\tikztotarget) + }}, + found style/.default={2*\mscget{lost symbol radius}}, + found style/.style={% + /msc, /tikz/line width=\mscget{line width},arrow style, + to path={ + (\tikztotarget) circle (0.5*#1) + \pgfextra{ \path[draw,solid,/tikz/line width=\mscget{line width}];} + ($ (\tikztotarget)! 0.5*#1 !(\tikztostart) $) -> (\tikztostart) + \tikztonodes + }}, + lost style/.default={2*\mscget{lost symbol radius}}, + lost style/.style={% + /msc, /tikz/line width=\mscget{line width},arrow style, + to path={ + (\tikztotarget) circle (0.5*#1) + \pgfextra{ \path[draw,solid,fill,/tikz/line width=\mscget{line width}];} + (\tikztostart) -> ($ (\tikztotarget)! 0.50*#1 !(\tikztostart) $) + \tikztonodes + }}, +} +\mscset{normal values} +%special treatments of keys that can be specified as right or left but could not +%be in the old verison of msc +\setlength{\envinstdist}{\mscget{left environment distance}} +\setlength{\inlineoverlap}{\mscget{left inline overlap}} +\setlength{\referenceoverlap}{\mscget{left reference overlap}} +\mscset{ + left environment distance/.initial=\the\envinstdist, % distance between environments and the % first level + right environment distance/.initial=\the\envinstdist, % distance between + left inline overlap/.initial=\the\inlineoverlap, + right inline overlap/.initial=\the\inlineoverlap, + left reference overlap/.initial=\the\referenceoverlap, + right reference overlap/.initial=\the\referenceoverlap +} +\def\msc@save@target#1{% + \def\msc@target{#1}} +\def\msc@save@start#1{% + \def\msc@start{#1}} +%defining styles to draw grid with help lines - usage e.g. \draw (0,-10) to[/msc/color grid] (10,0); +\mscset{ + /msc/grid/.style={ + to path={% + \pgfextra{% + \edef\msc@@target{(\tikztotarget)}% + \tikz@scan@one@point\msc@save@target\msc@@target\relax + \edef\msc@@start{(\tikztostart)}% + \tikz@scan@one@point\msc@save@start\msc@@start\relax + \draw[/msc/grid/minor lines] (\tikztostart) grid (\tikztotarget); + \draw[/msc/grid/major lines,line cap=rect] (\tikztostart) grid (\tikztotarget); + \msc@start + \pgfmathsetmacro{\msc@xa}{\the\pgf@x/1cm} + \pgfmathsetmacro{\msc@ya}{\the\pgf@y/1cm} + \msc@target + \pgfmathsetmacro{\msc@xb}{\the\pgf@x/1cm} + \pgfmathsetmacro{\msc@yb}{\the\pgf@y/1cm} + \pgfmathsetmacro{\msc@xc}{\msc@xa + \mscget{grid/major step}} + \pgfmathsetmacro{\msc@yc}{\msc@ya + \mscget{grid/major step}} + \foreach \x in {\msc@xa,\msc@xc,...,\msc@xb} + \node[/msc/grid/x labelstyle] at (\x,\msc@ya) {\pgfmathprintnumber{\x}}; + \foreach \y in {\msc@ya,\msc@yc,...,\msc@yb} + \node[/msc/grid/y labelstyle] at (\msc@xa,\y) {\pgfmathprintnumber{\y}}; + } + } + }, + /msc/color grid/.style={ + /msc/grid/labelstyle/.style={font=\tiny,text=blue}, + /msc/grid/minor line width=0.2pt, + /msc/grid/major line width=0.4pt, + /msc/grid/minor lines/.style={ + draw=green!10,line cap=rect, + /tikz/line width=\mscget{grid/minor line width}, + step=\mscget{grid/minor step} + }, + /msc/grid/major lines/.style={ + draw=red!10,line cap=rect, + /tikz/line width=\mscget{grid/major line width}, + step=\mscget{grid/major step} + }, + /msc/grid + }, + /msc/grid/.cd, + minor lines/.style={ + help lines,line cap=rect,dotted, + step=\mscget{grid/minor step} + }, + major lines/.style={ + help lines,line cap=rect, + /tikz/line width=\mscget{grid/major line width}, + step=\mscget{grid/major step} + }, + labelstyle/.style={font=\scriptsize,text=black}, + x labelstyle/.style={/msc/grid/labelstyle,below}, + y labelstyle/.style={/msc/grid/labelstyle,left}, + minor step/.initial=.2, + major step/.initial=1, + minor line width/.initial=0.3pt, + major line width/.initial=0.5pt, } -% -% 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}}% - }% - }% - }% +% And some internal counters +\newcount\c@mscinstcnt %number of intstances +\newcount\c@condition %number of conditions +\newcount\c@msclevelcnt %current level +% \newcount\c@maxlevelcnt %maximum level seen +%\advance\c@mscinstcnt by1 +\global\let\msc@tempa\relax +\global\let\msc@tempb\relax +%\newdimen\msc@x +%\newdimen\msc@y + +\newcommand{\mscgetx}[2]{% + \tikz@scan@one@point\pgfutil@firstofone#1\relax + \edef#2{\the\pgf@x}% } -% -% \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}% + +\newcommand{\mscgety}[2]{% + \tikz@scan@one@point\pgfutil@firstofone#1\relax + \edef#2{\the\pgf@y}% } -% -% \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}% + +% store the shifted level in #2 and level at which to draw message in #3 +% also update \c@maxlevelcnt +% #1 - level difference +\def\msc@getlevel shift#1#2#3{ + \pgfkeys{/pgf/number format/precision=0} + \pgfmathparse{\the\c@msclevelcnt + #1} + \pgfmathparse{max(\pgfmathresult,0)} + \pgfmathroundto{\pgfmathresult} + \edef#2{\pgfmathresult} %calculate destination level + \pgfmathparse{max((\the\c@msclevelcnt),#2)} + \pgfmathroundto{\pgfmathresult} + \xdef#3{\pgfmathresult} %calculate at which level to draw message + \pgfmathparse{max(#3,\c@maxlevelcnt)} + \pgfmathroundto{\pgfmathresult} + \xdef\c@maxlevelcnt{\pgfmathresult} %update global max level counter } + % -% \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}}% - }% -} +% * Shapes * % -%\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}% -} % +%% A rectangle with right side open % -% \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}% - }% +\pgfdeclareshape{right open rectangle} +{% + \nodeparts{text} + %% + %% Anchors + %% + \inheritsavedanchors[from=rectangle] + \inheritanchorborder[from=rectangle] + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{center} + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{mid} + \inheritanchor[from=rectangle]{mid west} + \inheritanchor[from=rectangle]{mid east} + \inheritanchor[from=rectangle]{base} + \inheritanchor[from=rectangle]{base west} + \inheritanchor[from=rectangle]{base east} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{south west} + \inheritanchor[from=rectangle]{south east} + \backgroundpath{ + % store lower right in xa/ya and upper right in xb/yb + \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y + \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y + \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}} + \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathclose + } +} +% +%% A rectangle with left side open +% +\pgfdeclareshape{left open rectangle} +{% + \nodeparts{text} + %% + %% Anchors + %% + \inheritsavedanchors[from=rectangle] + \inheritanchorborder[from=rectangle] + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{center} + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{mid} + \inheritanchor[from=rectangle]{mid west} + \inheritanchor[from=rectangle]{mid east} + \inheritanchor[from=rectangle]{base} + \inheritanchor[from=rectangle]{base west} + \inheritanchor[from=rectangle]{base east} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{south west} + \inheritanchor[from=rectangle]{south east} + \backgroundpath{ + % store lower right in xa/ya and upper right in xb/yb + \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y + \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y + \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}} + \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathclose + } +} +% +%% A rectangle with sloped sides +% +\pgfdeclareshape{condition shape} +{% + \nodeparts{text} + %% + %% Anchors + %% + \inheritsavedanchors[from=rectangle] + \inheritanchorborder[from=rectangle] + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{center} + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{mid} + \inheritanchor[from=rectangle]{mid west} + \inheritanchor[from=rectangle]{mid east} + \inheritanchor[from=rectangle]{base} + \inheritanchor[from=rectangle]{base west} + \inheritanchor[from=rectangle]{base east} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{south west} + \inheritanchor[from=rectangle]{south east} + \backgroundpath{ + % store lower right in xa/ya and upper right in xb/yb + % store lower right in xa/ya and upper right in xb/yb + \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y + \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y + \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}} + \pgfmathparse{\pgf@xa-(\pgf@yb-\pgf@ya)*0.5} + \pgf@xc=\pgfmathresult pt\relax + \pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5} + \pgf@yc=\pgfmathresult pt\relax + \pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}} + \pgfmathparse{\pgf@xb+(\pgf@yb-\pgf@ya)*0.5} + \pgf@xc=\pgfmathresult pt\relax + \pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5} + \pgf@yc=\pgfmathresult pt\relax + \pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathclose + } +} +%% A rectangle with sloped sides and strike out +% +\pgfdeclareshape{ncondition shape} +{% + \nodeparts{text} + %% + %% Anchors + %% + \inheritsavedanchors[from=rectangle] + \inheritanchorborder[from=rectangle] + \inheritanchor[from=rectangle]{north} + \inheritanchor[from=rectangle]{north west} + \inheritanchor[from=rectangle]{north east} + \inheritanchor[from=rectangle]{center} + \inheritanchor[from=rectangle]{west} + \inheritanchor[from=rectangle]{east} + \inheritanchor[from=rectangle]{mid} + \inheritanchor[from=rectangle]{mid west} + \inheritanchor[from=rectangle]{mid east} + \inheritanchor[from=rectangle]{base} + \inheritanchor[from=rectangle]{base west} + \inheritanchor[from=rectangle]{base east} + \inheritanchor[from=rectangle]{south} + \inheritanchor[from=rectangle]{south west} + \inheritanchor[from=rectangle]{south east} + \backgroundpath{ + % store lower right in xa/ya and upper right in xb/yb + % store lower right in xa/ya and upper right in xb/yb + \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y + \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y + \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}} + \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@yb}} + \pgfmathparse{\pgf@xa-(\pgf@yb-\pgf@ya)*0.5} + \pgf@xc=\pgfmathresult pt\relax + \pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5} + \pgf@yc=\pgfmathresult pt\relax + \pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}} + \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}} + \pgfmathparse{\pgf@xb+(\pgf@yb-\pgf@ya)*0.5} + \pgf@xc=\pgfmathresult pt\relax + \pgfmathparse{\pgf@yb*0.5+\pgf@ya*0.5} + \pgf@yc=\pgfmathresult pt\relax + \pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}} + \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yb}} + \pgfpathclose + } } -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% 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}% + +% \declinst[*] declares a new msc-instance and draws its head symbol +% the starred versions makes a fat instance. +% #1: msc/tikz options +% #2: nickname that can be used in \mess +% #3: name of the instance (above instance head symbol) +% #4: name of the instance (inside instance head symbol) +% Keys used: +% /msc/instance/nick - contains number for instance with nick +% /msc/instanceno/n - contains nick for instance with n, where n is a number +%\declinst(*){nickname}{instancenameabove}{instancenamewithin} +\def\declinst{\pgfutil@ifnextchar*{\msc@isstartrue\msc@declinst@nostar}{\msc@isstarfalse\msc@declinst@nostar*}} +\def\msc@declinst@nostar*{\pgfutil@ifnextchar[\msc@declinst@noopt{\msc@declinst@noopt[]}} +\def\msc@declinst@noopt[#1]#2#3#4{% + \msc@nameinstance{#2}{#1} + \msc@previousinstance{#2} + \begin{pgfscope} + \mscset{#1} + \node[/msc,draw=\mscget{draw head}, + instance head={#3}, name={msc@node#2}, + right=\mscget{instance distance} of msc@node\msc@inst@name.south east, +% inner sep=2pt, + anchor=south west, every instance head,#1]{#4}; + \end{pgfscope} + \advance\c@msclevelcnt by -1\relax + \msc@createlevelnodes{#2}{0} + \coordinate (msc@lastlevel#2) at (msc@node#2.south); + \advance\c@msclevelcnt by 1\relax + \msc@drawinstanceline{#2}{1} +} +% \dummyinst(*)[options]{createdinst} +\def\dummyinst{\pgfutil@ifnextchar*{\msc@isstartrue\msc@dummyinst@nostar}{\msc@isstarfalse\msc@dummyinst@nostar*}} +\def\msc@dummyinst@nostar*{\pgfutil@ifnextchar[\msc@dummyinst@noopt{\msc@dummyinst@noopt[]}} +\def\msc@dummyinst@noopt[#1]#2{% + \msc@nameinstance{#2}{#1} + \mscset{ + instance/#2/status/.initial=off + } + \begin{pgfscope} + \mscset{#1} + \msc@previousinstance{#2} + \pgfmathparse{max(\mscget{instance width}, width(\mscget{dummy text}) + +\pgfkeysvalueof{/pgf/inner xsep}*2+\mscget{line width}/2)} + \edef\msc@x{\pgfmathresult pt} + \node[/msc, name={msc@node#2}, + inner sep=2pt, + right=\mscget{instance distance} of msc@node\msc@inst@name.south east, + minimum width=\msc@x, + minimum height=\mscget{head height}, + anchor=south west, #1]{}; + \end{pgfscope} + \advance\c@msclevelcnt by -1\relax + \msc@createlevelnodes{#2}{0} + \coordinate (msc@lastlevel#2) at (msc@node#2.south); + \advance\c@msclevelcnt by 1\relax +} + +\def\inststart{\startinst}%old name of the command +%dd siple command \startinst[options]{instname}{text above}{text inside} +\def\startinst{\pgfutil@ifnextchar[\msc@startinst{\msc@startinst[]}} +\def\msc@startinst[#1]{ + \begin{pgfscope} + \edef\msc@option{#1}\edef\msc@name{}\edef\msc@creator{} + \pgfkeysactivatefamily{/msc/message options} + \pgfkeysfiltered{/msc,#1} + \msc@create +} +% \create[options]{name}[label position]{creator}[pos]{createdinst}{instancenameabove}{instancenamewithin} +\def\create{ + \begin{pgfscope} + \def\msc@option{} + \pgfutil@ifnextchar[\msc@create@opt{\msc@create@opt[]} +} +\def\msc@create@opt[#1]#2{ + \pgfkeysactivatefamily{/msc/message options} + \pgfkeysfiltered{/msc,#1} + \edef\msc@option{#1} + \def\msc@name{#2} + \pgfutil@ifnextchar[\msc@create@label{\msc@create@label[]} +} +\def\msc@create@label[#1]#2{ + \ifx#1t \mscset{label position=above} + \else \ifx#1b \mscset{label position=below} + \fi\fi + \edef\msc@creator{#2} + \pgfutil@ifnextchar[\msc@create{\msc@create@pos[\mscget{pos}]} +} +\def\msc@create@pos[#1]{ + \mscset{pos/.expanded=#1} + \msc@create +} +%\create{insance name}{label above}{label inside} +\def\msc@create#1#2#3{ +% \mscset{pos/.expanded=#1} + \pgfkeysifdefined{/msc/instance/#1/no}{ + \IfStrEq{off}{\mscget{instance/#1/status}}{ + \IfStrEq{fat}{\mscget{instance/#1/type}}{ + \edef\msc@tempa{(msc@node#1.east)++(-\mscget{line width}/2,0) coordinate (msc@node#1@r0) + coordinate (msc@node#1@r\the\c@msclevelcnt) + (msc@node#1.west)++(\mscget{line width}/2,0) coordinate (msc@node#1@l0) + coordinate (msc@node#1@l\the\c@msclevelcnt)} + }{% + \edef\msc@tempa{(msc@node#1.east)++(-\mscget{line width}/2,0) + coordinate (msc@node#1@r\the\c@msclevelcnt) + (msc@node#1.west)++(\mscget{line width}/2,0) + coordinate (msc@node#1@l\the\c@msclevelcnt)} + } + \edef\msc@tempb{ + [/msc, draw=\mscget{draw head}, instance head={#2}, name={msc@node#1}, every + instance head, + append after command={(msc@node#1.south) coordinate (msc@lastlevel#1) + \msc@tempa}, + \msc@option] at (msc@node#1|-msc@level\the\c@msclevelcnt){\unexpanded\expandafter{#3}}; + } + \adddraw{#1}{\the\c@msclevelcnt}{\expandafter\node\msc@tempb} + \pgfkeysifdefined{/msc/instance/\msc@creator/no}{ + \edef\msc@tempb{[\msc@option]{\unexpanded\expandafter{\msc@name}}{\msc@creator}{#1}} + \expandafter\mess\msc@tempb + }{} + \end{pgfscope} + \mscset{instance/#1/status=on} + }{ + \msc@instancestarted{#1}\end{pgfscope} + } +% \mscset{instance/#1/type=fat} + }{\msc@instundefinederr{#1}\end{pgfscope}} +} + +% creates nodes to which we draw a line when advancing a level +% #1 instance name +%associates name with number #1 in corresponding pgfkeys. It updates +%the right evironment + % #1 name of instance + % #2 options +\def\msc@nameinstance#1#2{ + \pgfkeysifdefined{/msc/instance/#1/no}{ + \msc@nicknamedefinederr{#1} + }{ + \advance\c@mscinstcnt by2\relax + \mscset{%update envright keys + instance/envright/no/.initial/.expanded=\the\c@mscinstcnt, + instanceno/\the\c@mscinstcnt/name/.initial/.expanded=envright + } + \advance\c@mscinstcnt by-1\relax% + \mscset{ + instance/#1/no/.initial/.expanded=\the\c@mscinstcnt, + instanceno/\the\c@mscinstcnt/name/.initial/.expanded=#1,% + instance/#1/status/.initial=on, %possible values: on, off (no draw), + instance/#1/cover/.initial=0, %how many times instance is covered + instance/#1/region/.initial=normal, %possible %values:normal,coregion,suspension,activation,seminormal + instance/#1/region level/.initial=0, + instance/#1/region width/.initial=0pt + } } + \begin{pgfscope}%parse options in scope not to propagate them + \mscset{#2}% + \ifnum\c@mscinstcnt<2\relax %the first instance + \coordinate[below=\mscget{first level height} of msc@level0] (msc@level1); + \fi + \ifmsc@isstar + \xdef\msc@tempa{fat} + \else + \xdef\msc@tempa{\mscget{fat}} + \fi + \end{pgfscope} + \mscset{/msc/instance/#1/type/.initial/.expand once=\msc@tempa} + \iftikz@fullytransformed %when fully transformed lines width is wrong - submitted bug nr 3597513. + \pgfmathparse{\msc@tempa + (0.5-0.5/\pgf@pt@bb)*\mscget{line width}} + \xdef\msc@tempa{\pgfmathresult} + \fi } -% -% \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} +%assigns the name of the previous instance to the \msc@inst@name + % #1 name or number of the instance +\def\msc@previousinstance#1{% + \pgfkeysifdefined{/msc/instanceno/#1/name}% + { \pgfmathsetcount{\c@pgf@counta}{#1} } + { \pgfkeysifdefined{/msc/instance/#1/no} + {\pgfmathsetcount{\c@pgf@counta}{\mscget{instance/#1/no}}}% + {\msc@instundefinederr{#1}} + } + \advance\c@pgf@counta by -1\relax% + \edef\msc@inst@name{\mscget{instanceno/\the\c@pgf@counta/name}} +} + +\def\msc@numsplit#1.#2{\def\msc@ta{#1}\def\msc@tb{#2}} +% \nextlevel increases \msc@currentheight by #1 * \level height +% (optional) #1: a nonnegative integer number (defaults to 1) +% or tkiz options +% +\def\nextlevel{ + \pgfutil@ifnextchar[\msc@nextlevelopt{\msc@nextlevelopt[1]} +} +\def\msc@nextlevelopt[#1]{% + \let\msc@tempheight\relax + \if!\ifnum9<1#1!\else_\fi + \mscset{/msc/level offset=#1} + \else + \msc@numsplit#1\relax + \if!\ifnum9<1\msc@ta!\else_\fi + \mscset{/msc/level offset=\msc@ta}%we get only + \if!\ifnum9<1\msc@tb!\else_\fi + \pgfmathsetmacro{\msc@tempheight}{0.\msc@tb*\mscget{level height}} + \msc@notpositiveintegerwarn{\msc@ta}{\msc@tb} + \fi + \fi + \fi + \mscgety{(msc@level\the\c@msclevelcnt)}{\msc@y} + \foreach \msc@tempa [evaluate=\msc@tempc using \msc@y-(\msc@tempa*\mscget{level height})] in {1 ,...,\mscget{level offset}} {% + \advance\c@msclevelcnt by 1\relax + \coordinate (msc@level\the\c@msclevelcnt) at (0,\msc@tempc pt); + \advance\c@msclevelcnt by -1\relax + \foreach \msc@tempb in {1,...,\c@mscinstcnt} { + \msc@createlevelnodes{\mscget{instanceno/\msc@tempb/name}}{\the\c@msclevelcnt} + } +% \message{-----Showing code for level=\the\c@msclevelcnt------------------- } +% \pgfkeys{/msc/level\the\c@msclevelcnt/draw/.show code,} + \pgfkeysifdefined{/msc/level\the\c@msclevelcnt/havedraw}{ + \begin{pgfscope} + \mscset{/msc/level\the\c@msclevelcnt/draw} + \msc@global@set{/msc/level\the\c@msclevelcnt/draw/.code={}} + \end{pgfscope} + }{ + } + \global\advance\c@msclevelcnt by 1\relax + } + \foreach \msc@tempb in {1,...,\c@mscinstcnt} { + \msc@drawinstanceline{\mscget{instanceno/\msc@tempb/name}}{\the\c@msclevelcnt} + } + \ifx\msc@tempheight\relax\else + \edef\msc@ta{\mscget{level height}} + \mscset{level height/.expanded=\msc@tempheight pt} + \nextlevel[1] + \mscset{level height/.expanded=\msc@ta} + \fi + \mscset{level offset=1} +} + +% \coordinate (msc@level\the\c@msclevelcnt) at (0,#2); +% draw a line for a given instance +% #1 name of the instance +% #2 level number +\def\msc@drawinstanceline#1#2{ + \IfStrEq{\mscget{instance/#1/status}}{on}{ +% ifnum0<\mscget{instance/#1/cover} \else + \mscgety{(msc@level#2)}{\msc@tempa} + \mscgety{(msc@lastlevel#1)}{\msc@dil} + \pgfmathparse{max(\msc@tempa-\msc@dil,\mscget{instance/#1/cover})} + \ifnum0<\pgfmathresult\relax %draw only if last level is above current level + \mscgety{(msc@level#2)}{\msc@io}\msc@setlastlevel{#1}{\msc@io} + \else + \msc@StrEqEither{\mscget{instance/#1/region}}{normal}{seminormal}{ + \draw[/msc,instance line,every instance line] + (msc@lastlevel#1-|msc@node#1@l0)--(msc@level#2-|msc@node#1@l0) + (msc@lastlevel#1-|msc@node#1@r0)--(msc@level#2-|msc@node#1@r0); + \mscgety{(msc@level#2)}{\msc@io}\msc@setlastlevel{#1}{\msc@io} + }{ +% \msc@regbody{#1}{#2} + } + \fi + }{} +} + +% create nodes at a current level for a given instance +% #1 name of the instance +% #2 level number +\def\msc@createlevelnodes#1#2{ +%assume node msc@level#2 exists + \IfEqCase{\mscget{instance/#1/type}}{ + {fat} { + \coordinate[xshift=\mscget{line width} /2](msc@node#1@l#2) at (msc@node#1.west|-msc@level#2); + \coordinate[xshift=-\mscget{line width} /2] (msc@node#1@r#2) at (msc@node#1.east|-msc@level#2); + \IfStrEq{\mscget{instance/#1/region}}{seminormal}{ + \msc@global@set{instance/#1/region=normal} + }{} + } + {normal} {% + \msc@StrEqEither{\mscget{instance/#1/region}}{normal}{coregion}{% + \coordinate (msc@node#1@r#2) at (msc@node#1 |-msc@level#2); + \coordinate (msc@node#1@l#2) at (msc@node#1 |-msc@level#2); + } + {% + \msc@StrEqEither{\mscget{instance/#1/region}}{activation}{suspension} { + \path let \p1=(msc@node#1), \p2=(msc@level#2) in + coordinate(msc@node#1@l#2) at (\x1-\mscget{instance/#1/region width}/2,\y2) + coordinate(msc@node#1@r#2) at (\x1+\mscget{instance/#1/region width}/2,\y2); + } + { + \IfStrEq{\mscget{instance/#1/region}}{seminormal}{ + \path let \p1=(msc@node#1), \p2=(msc@level#2) in + coordinate(msc@node#1@l#2) at (\x1-\mscget{instance/#1/region width}/2,\y2) + coordinate(msc@node#1@r#2) at (\x1+\mscget{instance/#1/region width}/2,\y2); + \msc@global@set{instance/#1/region=normal} + }{%debug message + \message{[msc] Unknown region type: \mscget{instance/#1/region} for the nick: #1} + } + } + } + } + [\message{[msc] Unknown instance type: \mscget{instance/#1/type} for the nick: #1}] + } +% } +% { } +} +% \mess(*)[side]{name}[label position]{sender}[pos]{receiver}[level shift] +\def\mess{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@mess@nostar}{\msc@isstarfalse\msc@mess@nostar*} +} +\def\msc@mess@nostar*{\pgfutil@ifnextchar[\msc@messopt{\msc@messopt[]}} +\def\msc@messopt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else \ifx#1b \else \ifx#1t %ignoring t and b for backward compatibility + \else + \pgfkeysactivatefamily{/msc/message options} + \pgfkeysfiltered{/msc,#1} + \def\msc@options{#1} +% \pgfutil@ifundefined{msc@mess@side}{\def\msc@mess@side{\mscget{side}}}{} + \fi \fi \fi + \fi + \pgfutil@ifnextchar[{\msc@messopt}{\msc@mess@threeopt} +} +\def\msc@mess@threeopt#1{%parsing of {name} + \def\msc@mess@name{#1} + \pgfutil@ifnextchar[\msc@mess@twoopt{\msc@mess@twoopt[\mscget{label position}]} +} +\def\msc@mess@twoopt[#1]#2{%parsing of [label position] and {sender} + \ifx#1l \mscset{label position=left} + \else \ifx#1r \mscset{label position=right} + \else \ifx#1t \mscset{label position=above} + \else \ifx#1b \mscset{label position=below} + \fi \fi \fi \fi + \xdef\msc@sender{#2} + \pgfutil@ifnextchar[\msc@mess@oneopt{\msc@mess@oneopt[\mscget{pos}]} +} +\def\msc@mess@oneopt[#1]#2{%parsing of [placement] and {receiver} + \mscset{pos/.expanded=#1} + \xdef\msc@receiver{#2} + \IfStrEq{\msc@receiver}{\msc@sender}{ + \edef\msc@tempb{\mscget{offset}} + }{ + \edef\msc@tempb{\mscget{level shift}} + } + \pgfutil@ifnextchar[{\msc@mess@noopt}{\msc@mess@noopt[\msc@tempb]} +} + +\def\msc@mess@noopt[#1]{%parsing of [level shift] + \def\msc@undefined{false} + \msc@getlevel shift{#1}{\msc@level shift}{\msc@tempa} + \ifx\msc@sender\msc@receiver %self message + \IfStrEq{\mscget{label position}}{above}{ + \mscset{label position=\mscget{side}} + }{} + \pgfkeysifdefined{/msc/instance/\msc@receiver/no}{%instance name + \IfStrEq{\mscget{side}}{left}{ + \msc@selfmess{msc@node\msc@receiver @l\the\c@msclevelcnt}{msc@node\msc@receiver @l\msc@level shift}{-\mscget{self message width}} + }{ + \msc@selfmess{msc@node\msc@receiver @r\the\c@msclevelcnt}{msc@node\msc@receiver @r\msc@level shift}{\mscget{self message width}} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@receiver}{% neither instance name nor reference node + \def\msc@undefined{true} + \msc@instundefinederr{\msc@receiver} + }{% reference node + \IfStrEq{\mscget{side}}{left}{ + \msc@selfmess{msc@node\msc@receiver|-msc@level\the\c@msclevelcnt}% + {msc@node\msc@receiver|-msc@level\msc@level shift}{-\mscget{self message width}} + }{ + \msc@selfmess{msc@node\msc@receiver|-msc@level\the\c@msclevelcnt}% + {msc@node\msc@receiver|-msc@level\msc@level shift} {\mscget{self message width}} + } + } + } + \else %not self message + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@receiver} { + \def\msc@undefined{true} + \msc@instundefinederr{\msc@receiver} + }{ + \mscgetx{(msc@node\msc@receiver)}{\msc@minx} + } + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@sender} { + \def\msc@undefined{true} + \msc@instundefinederr{\msc@sender} + }{ + \mscgetx{(msc@node\msc@sender)}{\msc@maxx} + } + \IfStrEq{\msc@undefined}{false}{ + \pgfkeysifdefined{/msc/instance/\msc@sender/no}{%instance name +% \pgfmathparse{\msc@maxx-\msc@minx} + \pgfmathparse{ifthenelse((\msc@maxx-\msc@minx)<0,"r","l")} + \edef\msc@left{msc@node\msc@sender @\pgfmathresult\the\c@msclevelcnt} + }{ + \def\msc@left{msc@node\msc@sender|-msc@level\the\c@msclevelcnt} + } + \pgfkeysifdefined{/msc/instance/\msc@receiver/no}{%instance name + \pgfmathparse{ifthenelse((\msc@maxx-\msc@minx)<0,"l","r")} + \edef\msc@right{msc@node\msc@receiver @\pgfmathresult\msc@level shift} + }{ + \def\msc@right{msc@node\msc@receiver|-msc@level\msc@level shift} + } + \msc@mess{\msc@left}{\msc@right}%stores result in \msc@tempb + }{} + \fi + \IfStrEq{\msc@undefined}{false}{ + \end{pgfscope} + \addDdraw{\msc@sender}{\msc@receiver}{\msc@tempa}{\expandafter\draw\msc@tempb} + }{ + \end{pgfscope} } } -% -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%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 - }% +% #1 - sender node +% #2 - receiver node +% #3 - message dist +% result defined in \msc@tempb +\def\msc@selfmess#1#2#3{ + \IfStrEq{\mscget{label position}}{left}{\xdef\msc@tempc{-1}}{\xdef\msc@tempc{1}} + \xdef\msc@tempb{[\mscget{label position},/msc,message,message loop={#3}, + \ifmsc@isstar replay,\fi, inner sep=0pt, + /tikz/pos=\mscget{pos}, every message, \msc@options] + (#1) + to node[xshift=\msc@tempc*\mscget{label distance}](msc@lastnode){\expandafter\noexpand\msc@mess@name} + (#2); + }%use macro to expand parameters +} +% #1 - sender node +% #2 - receiver node +% result defined in \msc@tempb +\def\msc@mess#1#2{ + \IfSubStr{\mscget{label position}}{above}{\xdef\msc@tempc{1}}{\xdef\msc@tempc{-1}} + \xdef\msc@tempb{[/msc,\mscget{label position},message, + \ifmsc@isstar replay,\fi, inner sep=0pt, % + /tikz/pos=\mscget{pos}, every message, \msc@options] + (#1) -> + node[yshift=\msc@tempc*\mscget{label distance}](msc@lastnode){\unexpanded\expandafter{\msc@mess@name}}(#2);%cheating %and using eTeX expansion + % to use pure TeX see http://tex.stackexchange.com/questions/40674/replacement-for-unexpanded-without-etex-extension + } } -% -\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 - }% +%add code to be executed at given level +% #1 - name of the instance +% #2 - number of level at which to add the code +% #3 - code to be added (expanded once - so prefix with \expandafter) +\def\adddraw#1#2#3{ + \msc@StrEqEither{#1}{envright}{envleft} { + \msc@global@set{/msc/levelenv/draw/.append code/.expand once={#3}, + /msc/levelenv/havedraw/.initial=true} + }{ + \msc@global@set{/msc/level#2/draw/.append code/.expand once={#3}, + /msc/level#2/havedraw/.initial=true} + } } -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% 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}% - }% +%add code to be executed at given level +% #1 - name of the instance +% #2 - name of the second instance +% #3 - number of level at which to add the code +% #4 - code to be added (expanded once - so prefix with \expandafter) +\def\addDdraw#1#2#3#4{ + \msc@StrEqEither{#1}{envright}{envleft} { + \msc@global@set{/msc/levelenv/draw/.append code/.expand once={#4}, + /msc/levelenv/havedraw/.initial=true} + }{ + \msc@StrEqEither{#2}{envright}{envleft} { + \msc@global@set{/msc/levelenv/draw/.append code/.expand once={#4}, + /msc/levelenv/havedraw/.initial=true} + }{ + \msc@global@set{/msc/level#3/draw/.append code/.expand once={#4}, + /msc/level#3/havedraw/.initial=true} + } + } } -% -% \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}% - }% +% \msccomment[position]{text}{instname} +\def\msccomment{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@msccomment@nostar}{\msc@isstarfalse\msc@msccomment@nostar*} +} +\def\msc@msccomment@nostar*{\pgfutil@ifnextchar[\msc@msccomment@opt{\msc@msccomment@opt[]}} +\def\msc@msccomment@opt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \pgfkeysactivatefamily{/msc/msccomment options} + \pgfkeysfiltered{/msc,#1} + \def\msc@options{#1} +% \pgfutil@ifundefined{msc@mess@side}{\def\msc@mess@side{\mscget{side}}}{} + \fi + \fi + \pgfutil@ifnextchar[{\msc@msccomment@opt}{\msc@msccomment@noopt} } -% -% -\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)% + +\def\msc@msccomment@noopt#1#2{%parsing of {text} + \edef\msc@undefined{false} + \edef\msc@instname{#2} + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt} + } { + \edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt} } - {% - \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)% + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node + \edef\msc@undefined{true} + \msc@instundefinederr{\msc@instname} } - \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)% + { + \edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt} } - {\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)% + } + \IfStrEq{\msc@undefined}{false}{ + \IfStrEq{\mscget{side}}{left}{ + \def\msc@anchor{east} + \edef\msc@dist{-\mscget{msccomment distance}} + } { + \def\msc@anchor{west} + \edef\msc@dist{\mscget{msccomment distance}} } - \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}% + \xdef\msc@tempb{[/msc,msccomment,msccomment line, + every msccomment, \msc@options] + let \noexpand\p1 = (\msc@node) + in (\noexpand\x1+\msc@dist,\noexpand\y1) + node [/msc,draw,solid,\mscget{side} open rectangle,anchor=\msc@anchor, + append after command={(\msc@node) + -- (\noexpand\tikzlastnode)}, + every msccomment, \msc@options] {#1}; + }%use macro to expand parameters + \end{pgfscope} + \adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb} + }{ + \msc@instundefinederr{\msc@instname}\end{pgfscope} } } - -\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}% - }% +% \action(*){name}{instance} +% \naction(*){name}{instance} +\def\naction{ + \begin{pgfscope}%,append after command={node[draw,cross out]{}} + \def\msc@crossout{,append after command={ + [shorten >=1.2*\noexpand\mscget{line width}, + shorten <=1.2*\noexpand\mscget{line width}] + (\noexpand\tikzlastnode.north west) edge (\noexpand\tikzlastnode.south east) + (\noexpand\tikzlastnode.north east) edge (\noexpand\tikzlastnode.south west)}} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@action@nostar}{\msc@isstarfalse\msc@action@nostar*} +} +\def\action{ + \begin{pgfscope} + \def\msc@crossout{} + \def\msc@options{} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@action@nostar}{\msc@isstarfalse\msc@action@nostar*} +} +% #1 options +% #2 name +% #3 insstance +\def\msc@action@nostar*{\pgfutil@ifnextchar[\msc@action@opt{\msc@action@opt[]}} +\def\msc@action@opt[#1]#2#3{%parsing of [side] and [options] + \pgfkeysactivatefamily{/msc/action options} + \pgfkeysfiltered{/msc,#1} + \def\msc@options{#1} + \xdef\msc@instname{#3} + \ifmsc@isstar + \def\msc@tempa{} + \else + %\msc@savebox{#2} + \edef\msc@tempa{, + %text height={min({\the\ht\msc@box},\mscget{action height})}, + %text depth={\the\dp\msc@box}, + %inner sep=0, + align=center, + text width={max( \mscget{action width},\noexpand\noexpand\noexpand\x2 - + \noexpand\noexpand\noexpand\x1)-2*\mscget{label distance}} + } + \fi + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \xdef\msc@tempb{[, ] + let \noexpand\p1 = (msc@node\msc@instname @l\the\c@msclevelcnt), + \noexpand\p2 = (msc@node\msc@instname @r\the\c@msclevelcnt) in + ( {\noexpand\x1+(\noexpand\x2-\noexpand\x1)/2},\noexpand\y1) + node[/msc, line cap=round, + yshift=\mscget{line width}/2, anchor=north, + minimum height=\mscget{action height}, + minimum width= {max( \mscget{action width},\noexpand\x2 - + \noexpand\x1)} \msc@tempa, draw \msc@crossout, + inner sep=\mscget{label distance}, + every action, /tikz/line width=\mscget{line width},\msc@options + ](msc@tempnode){\unexpanded\expandafter{#2}}; + \noexpand\msc@StrEqEither{\msc@instname}{envright}{envleft}{}{ + \noexpand\mscgety{(msc@tempnode.south)}{\noexpand\msc@y} + \noexpand\msc@setlastlevel{\msc@instname}{\noexpand\msc@y} } } - }{% 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}% - \edef\msc@scratch{\msc@circlefillstyle}% - \pscircle[fillstyle=solid,fillcolor=\msc@scratch]% - (\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}}% - }% + \end{pgfscope} + \msc@StrEqEither{\mscget{instance/#3/region}}{normal}{seminormal}{}{ + \msc@regbody{#3}{\the\c@msclevelcnt} + \msc@regbar{#3}{\mscget{instance/#3/region level}} + } + \adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb} + }{ + \msc@instundefinederr{\msc@instname}\end{pgfscope} + } } -% -% -% \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}% +% \settimer[placement]{name}{instance} +\def\settimer{ + \begin{pgfscope} + \def\msc@options{} \def\msc@timertype{settimer style} + \pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]} +} +% \timeout[placement]{name}{instance} +\def\timeout{ + \begin{pgfscope} + \def\msc@options{} \def\msc@timertype{timeout style} + \pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]} +} +% \stoptimer[placement]{name}{instance} +\def\stoptimer{ + \begin{pgfscope} + \def\msc@options{} \def\msc@timertype{stoptimer style} + \pgfutil@ifnextchar[\msc@timer@opt{\msc@timer@opt[]} +} +% #1 - options or "l" or "r" +\def\msc@timer@opt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \pgfkeysactivatefamily{/msc/msccomment options} + \pgfkeysfiltered{/msc,#1} + \def\msc@options{#1} + \fi + \fi + \pgfutil@ifnextchar[{\msc@timer@opt}{\msc@timer} +} +% #1 - label +% #2 - instance name +\def\msc@timer#1#2{ + \edef\msc@undefined{false} + \edef\msc@instname{#2} + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt} + } { + \edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node + \edef\msc@undefined{true} + \msc@instundefinederr{\msc@instname} + } + { + \edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt} + } + } + \IfStrEq{\msc@undefined}{false}{ + \IfStrEq{\mscget{side}}{left}{ + \def\msc@anchor{east} + \edef\msc@timer@dist{-\mscget{self message width}} + \edef\msc@label@dist{-\mscget{label distance}} + } { + \edef\msc@timer@dist{\mscget{self message width}} + \def\msc@anchor{west} + \edef\msc@label@dist{\mscget{label distance}} + } + \xdef\msc@tempb{[/msc,\msc@timertype={\mscget{timer width}}, + every timer, \msc@options] + let \noexpand\p1 = (\msc@node) + in (\noexpand\x1+\msc@timer@dist,\noexpand\y1) + node [xshift=\msc@label@dist,/msc,anchor=\msc@anchor]{#1} to (\noexpand\x1,\noexpand\y1); + }%use macro to expand parameters + \end{pgfscope} + \adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb} + }{ + \msc@instundefinederr{#2}\end{pgfscope} + } } -% -% \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% +%\setstoptimer[placement]{name}{instance}[offset] +\def\setstoptimer{ + \begin{pgfscope} + \def\msc@options{} \def\msc@timertype{setstoptimer style} + \pgfutil@ifnextchar[\msc@fulltimer@opt{\msc@fulltimer@opt[]} +} +%\settimeout[placement]{name}{instance}[offset] +\def\settimeout{ + \begin{pgfscope} + \def\msc@options{} \def\msc@timertype{settimeout style} + \pgfutil@ifnextchar[\msc@fulltimer@opt{\msc@fulltimer@opt[]} +} + +% #1 - options or "l" or "r" +\def\msc@fulltimer@opt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \pgfkeysactivatefamily{/msc/msccomment options} + \pgfkeysfiltered{/msc,#1} + \def\msc@options{#1} + \fi + \fi + \pgfutil@ifnextchar[{\msc@fulltimer@opt}{\msc@fulltimer} +} +\def\msc@fulltimer#1#2{ + \xdef\msc@instname{#2} + \def\msc@name{#1} + \pgfutil@ifnextchar[{\msc@fulltimer@noopt}{\msc@fulltimer@noopt[\mscget{offset}]} +} +\def\msc@fulltimer@noopt[#1]{ + \edef\msc@undefined{false} + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node\msc@instname @l} + } { + \edef\msc@node{msc@node\msc@instname @r} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node + \edef\msc@undefined{true} + \msc@instundefinederr{\msc@instname} + } + { + \edef\msc@node{msc@node\msc@instname|-msc@level} + } + } + \IfStrEq{\msc@undefined}{false}{ +% \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \msc@getlevel shift{#1}{\msc@level shift}{\msc@drawlevel} + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@mess@dist{-\mscget{self message width}} + \edef\msc@label@dist{-\mscget{label distance}} + \def\msc@anchor{east} + }{ + \edef\msc@mess@dist{\mscget{self message width}} + \edef\msc@label@dist{\mscget{label distance}} + \def\msc@anchor{west} + } + \xdef\msc@tempb{[/msc,\msc@timertype={\msc@mess@dist}{\mscget{timer width}}, + every timer,\msc@options] + (\msc@node\the\c@msclevelcnt) + node [xshift=\msc@label@dist+\msc@mess@dist,/msc,anchor=\msc@anchor]{\msc@name} + to (\msc@node\msc@level shift); + } + \end{pgfscope} + \adddraw{\expandafter\noexpand\msc@instname}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb} +% \edef\msc@drawlevel{0} + }{ + \end{pgfscope}\msc@instundefinederr{\msc@instname} } - \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)% - } - } - } +% \mscmark[position]{name}{instname} +\def\mscmark{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar[\msc@mark@opt{\msc@mark@opt[]} +} +\def\msc@mark@opt[#1]{%parsing of [side] and [options] + \IfEqCase{#1}{% + {l}{\mscset{side=left}}% + {r}{\mscset{side=right}}% + {t}{\mscset{position=above}}% + {b}{\mscset{position=below}}% + {tl}{\mscset{side=left,position=above}}% + {tr}{\mscset{side=right,position=above}}% + {bl}{\mscset{side=left,position=below}}% + {br}{\mscset{side=right,position=below}}% + }[% + \mscset{#1} + \def\msc@options{#1} + ] + \pgfutil@ifnextchar[{\msc@mark@opt}{\msc@mark} +} + +\def\msc@mark#1#2{ + \def\msc@undefined{false} + \pgfkeysifdefined{/msc/instance/#2/no}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node#2@l\the\c@msclevelcnt} + } { + \edef\msc@node{msc@node#2@r\the\c@msclevelcnt} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node#2}{% neither instance name nor reference node + \edef\msc@undefined{true} + \msc@instundefinederr{#2} + } + { + \edef\msc@node{msc@node#2|-msc@level\the\c@msclevelcnt} + } + } + \IfStrEq{\msc@undefined}{false}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@anchor@l{south east} + \edef\msc@anchor@r{south west} + \edef\msc@dist{-\mscget{mark distance}} + } { + \edef\msc@dist{\mscget{mark distance}} + \edef\msc@anchor@l{south west} + \edef\msc@anchor@r{south east} + } + \IfStrEq{\mscget{position}}{above}{ + \edef\msc@mark@ydist{0.5*\mscget{mark distance}} + }{ + \IfStrEq{\mscget{position}}{below}{ + \edef\msc@mark@ydist{-0.5*\mscget{mark distance}} + } + { + \IfStrEq{\mscget{position}}{mid}{ + \edef\msc@mark@ydist{0pt} + }{%unknown + } + } + } + \xdef\msc@tempb{[/msc,mscdash,/tikz/line width=\mscget{line width}, every mscmark, \msc@options] + (\msc@node) + ++(\msc@dist,\msc@mark@ydist) + node[anchor=\msc@anchor@l,inner sep=\mscget{label distance}, append after command={ + (\msc@node)-- + (\noexpand\tikzlastnode .\msc@anchor@l)--(\noexpand\tikzlastnode .\msc@anchor@r) + }] {#1}; } - {% 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)% - } + \end{pgfscope} + \adddraw{#2}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb} + }{} +} +% \measure(*)[placement]{name}{instance1}{instance2}[offset] +\def\measure{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@measure@nostar}{\msc@isstarfalse\msc@measure@nostar*} +} +\def\msc@measure@nostar*{\pgfutil@ifnextchar[\msc@measure@opt{\msc@measure@opt[]}} +\def\msc@measure@opt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \mscset{#1} + \def\msc@options{#1} + \fi + \fi + \pgfutil@ifnextchar[{\msc@measure@opt}{\msc@measure@noopt} +} + +\def\msc@measure@noopt#1#2#3{ + \def\msc@measure@name{#1} + \xdef\msc@instnameI{#2} + \xdef\msc@instnameII{#3} + \pgfutil@ifnextchar[{\msc@measure@final}{\msc@measure@final[\mscget{offset}]} +} + +\def\msc@measure@final[#1]{ + \pgfkeysifdefined{/msc/instance/\msc@instnameI/no}{ + \pgfkeysifdefined{/msc/instance/\msc@instnameII/no}{ + \msc@getlevel shift{#1}{\msc@level shift}{\msc@drawlevel} + \ifmsc@isstar\def\msc@style{measure* style}\else\def\msc@style{measure style}\fi + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@nodeI{msc@node\msc@instnameI @l\the\c@msclevelcnt} + \edef\msc@nodeII{msc@node\msc@instnameII @l\msc@level shift} + \edef\msc@dist{-\mscget{measure distance}-\noexpand\noexpand\noexpand\msc@x+ + min(\noexpand\noexpand\noexpand\msc@x,\noexpand\noexpand\noexpand\msc@y)} + \edef\msc@anchor{east} + } { + \edef\msc@nodeI{msc@node\msc@instnameI @r\the\c@msclevelcnt} + \edef\msc@nodeII{msc@node\msc@instnameII @r\msc@level shift} + \edef\msc@dist{\mscget{measure distance}-\noexpand\noexpand\noexpand\msc@x + +max(\noexpand\noexpand\noexpand\msc@x,\noexpand\noexpand\noexpand\msc@y)} + \edef\msc@anchor{west} + } + \xdef\msc@tempa{ + \noexpand\mscgetx{(\msc@nodeI)}{\noexpand\msc@x} + \noexpand\mscgetx{(\msc@nodeII)}{\noexpand\msc@y} + \noexpand\pgfmathparse{\msc@dist} + \noexpand\edef\noexpand\msc@dist{\noexpand\pgfmathresult} + } + \xdef\msc@tempb{[/msc,draw, mscdash, + \msc@style={\noexpand\msc@dist pt}{\mscget{measure symbol width}}, every measure, + \msc@options] (\msc@nodeI) to + node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{\unexpanded\expandafter{\msc@measure@name}} + (\msc@nodeII); +% \noexpand\path ($(a) !\mscget{pos}! (b)$) +% node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{text}; } - } - }% - }% - }% -}% -% -% \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}}{ - \edef\msc@scratch{\msc@instfootcolor{#1}}% - \psframe[dimen=middle,fillstyle=solid,fillcolor=\msc@scratch,linestyle=\msc@instlinestyle{#1}](\tmp@Xa,-\tmp@Ya)(\tmp@Xb,-\tmp@Yb)% - }{% else, no foot symbol drawing% + \end{pgfscope} + \addDdraw{\msc@instnameI}{\msc@instnameII}{\expandafter\noexpand\msc@drawlevel}{\expandafter\noexpand\msc@tempa} + \addDdraw{\msc@instnameI}{\msc@instnameII}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb} + }{ + \msc@instundefinederr{\msc@instnameII}\end{pgfscope} + } + }{ + \msc@instundefinederr{\msc@instnameI}\end{pgfscope} } } -% -% \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. The starred version adjusts the width -% and height of the action symbol -\def\action{\@ifstar{\msc@actionstar}{\msc@actionnostar}} - -\def\msc@actionstar#1#2{ - \setlength{\tmp@Xc}{\actionwidth}% - \setlength{\tmp@Yc}{\actionheight}% - \savebox{\tmp@box}{#1} - \setlength{\actionwidth}{\wd\tmp@box + 2\labeldist} - \setlength{\actionheight}{\ht\tmp@box + \dp\tmp@box +2\labeldist} - \msc@actionnostar{\usebox{\tmp@box}}{#2}% - \setlength{\actionwidth}{\tmp@Xc}% - \setlength{\actionheight}{\tmp@Yc}% -} - -\def\msc@actionnostar#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}% - }% +%\measurestart(*)[placement]{name}{instance}{gate} +\def\measurestart{ + \begin{pgfscope} + \def\msc@options{} + \def\msc@sign{} + \pgfutil@ifnextchar*{\edef\msc@style{measurestart* style}\msc@measuregap@nostar}{\edef\msc@style{measurestart style}\msc@measuregap@nostar*} +} +% \measureend(*)[placement]{name}{instance}{gate} +\def\measureend{ + \begin{pgfscope} + \def\msc@options{} + \def\msc@sign{-1*} + \pgfutil@ifnextchar*{\edef\msc@style{measurestart* style}\msc@measuregap@nostar}{\edef\msc@style{measurestart style}\msc@measuregap@nostar*} +} +\def\msc@measuregap@nostar*{\pgfutil@ifnextchar[\msc@measuregap@opt{\msc@measuregap@opt[]}} +\def\msc@measuregap@opt[#1]{%parsing of [side] and [options] + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \mscset{#1} + \def\msc@options{#1} + \fi + \fi + \pgfutil@ifnextchar[{\msc@measuregap@opt}{\msc@measuregap@noopt} +} + +\def\msc@measuregap@noopt#1#2#3{ + \edef\msc@text{#1} + \gdef\msc@instname{#2} + \edef\msc@gate{#3} + \pgfutil@ifnextchar[{\msc@measuregap@final}{\msc@measuregap@final[\mscget{offset}]} +} + +\def\msc@measuregap@final[#1]{ + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \msc@getlevel shift{\msc@sign#1}{\msc@level shift}{\msc@drawlevel} + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@nodeI{msc@node\msc@instname @l\the\c@msclevelcnt} + \edef\msc@nodeII{msc@node\msc@instname @l\msc@level shift} + \edef\msc@dist{-\mscget{measure distance}} + \edef\msc@anchor{east} + } { + \edef\msc@nodeI{msc@node\msc@instname @r\the\c@msclevelcnt} + \edef\msc@nodeII{msc@node\msc@instname @r\msc@level shift} + \edef\msc@dist{\mscget{measure distance}} + \edef\msc@anchor{west} + } + \xdef\msc@tempb{[/msc,mscdash,draw, + \msc@style={\msc@dist}{\mscget{measure symbol width}}, every measure, + \msc@options] (\msc@nodeI) to node[/msc,anchor=\msc@anchor, inner + sep=\mscget{label distance}, every measure, \msc@options]{\msc@text} (\msc@nodeII); + \noexpand\path (b) node[/msc,anchor=\msc@anchor, inner sep=\mscget{label distance}, every measure, \msc@options]{\msc@gate}; + } + \end{pgfscope} + \adddraw{\msc@instname}{\expandafter\noexpand\msc@drawlevel}{\expandafter\draw\msc@tempb} + }{ + \msc@instundefinederr{\msc@instname}\end{pgfscope} + } +} + +% \lost[side]{name}[label position]{gate}{instance}[pos] +\def\lost{ + \begin{pgfscope} + \def\msc@options{} + \def\msc@style{lost style} + \pgfutil@ifnextchar[{\msc@lost@opt}{\msc@lost@opt[]} +} +% \found[pos]{name}[label position]{gate}{instance}[placement] +\def\found{ + \begin{pgfscope} + \def\msc@options{} + \def\msc@style{found style} + \pgfutil@ifnextchar[{\msc@lost@opt}{\msc@lost@opt[]} +} +\def\msc@lost@opt[#1]#2{ + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \mscset{#1} + \def\msc@options{#1} + \fi + \fi + \def\msc@text{#2} + \pgfutil@ifnextchar[{\msc@lost@noopt}{\msc@lost@noopt[]} +} +\def\msc@lost@noopt[#1]#2#3{ + \mscset{label position=above} + \expandafter\ifx#1b \mscset{label position=below} \fi + \def\msc@gate{#2} + \xdef\msc@instname{#3} + \pgfutil@ifnextchar[{\msc@lost@final}{\msc@lost@final[\mscget{pos}]} +} +\def\msc@lost@final[#1]{ + \def\msc@undefined{false} + \pgfkeysifdefined{/msc/instance/\msc@instname/no}{ + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node\msc@instname @l\the\c@msclevelcnt} + } { + \edef\msc@node{msc@node\msc@instname @r\the\c@msclevelcnt} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node\msc@instname}{% neither instance name nor reference node + \edef\msc@undefined{true} + \msc@instundefinederr{\msc@instname} + } + { + \edef\msc@node{msc@node\msc@instname|-msc@level\the\c@msclevelcnt} + } + } + \IfStrEq{\msc@undefined}{false}{ + \mscset{pos=#1} + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@dist{-\mscget{self message width}} + \edef\msc@anchor{east} + } { + \edef\msc@dist{\mscget{self message width}} + \edef\msc@anchor{west} + } + \xdef\msc@tempb{[/msc,draw, + \msc@style={2*\mscget{lost symbol radius}}, every lostfound, + \msc@options] (\msc@node) to node[/msc,\mscget{label position}, inner + sep=\mscget{label distance}, every lostfound, \msc@options]{\unexpanded\expandafter{\msc@text}} + ++(\msc@dist,0); + \noexpand\path(\msc@node) ++(\msc@dist,0) + node[/msc,above,anchor=\msc@anchor,% + inner sep=\mscget{label distance}, every lostfound, \msc@options]{\msc@gate}; + } + \end{pgfscope} + \adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\draw\msc@tempb} + }{} } -% -% \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. The % starred version adjusts the width and the height of the condition symbol. % #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 +% - 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{\@ifstar{\msc@conditionstar}{\msc@conditionnostar}} - -\def\msc@conditionstar#1#2{ -% \message{(msc: conditionheight: \msc@conditionheight, actionheight: \msc@actionheight)} - \setlength{\tmp@Xd}{\conditionoverlap}% - \setlength{\tmp@Yd}{\conditionheight}% - \savebox{\tmp@box}{#1} - \setlength{\conditionoverlap}{.5\wd\tmp@box + \labeldist} - \setlength{\conditionheight}{\ht\tmp@box + \dp\tmp@box + 2\labeldist} - \msc@conditionnostar{\usebox{\tmp@box}}{#2} -% \settowidth{\conditionoverlap}{#1}% -% \setlength{\conditionoverlap}{.5\conditionoverlap} -% \settoheight{\conditionheight}{\rule{0pt}{\tmp@Yd-1ex} #1}% -% \addtolength{\conditionheight}{1ex} -% \msc@conditionnostar{#1}{#2}% - \setlength{\conditionoverlap}{\tmp@Xd}% - \setlength{\conditionheight}{\tmp@Yd}% -} - -\def\msc@conditionnostar#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}% +% \condition(*)[options]{text}{instancelist} +\def\condition{ + \advance\c@condition by1\relax + \begin{pgfscope} + \edef\msc@shape{condition shape} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@cond@star}{\msc@isstarfalse\msc@cond@star*} +} +\def\ncondition{ + \begin{pgfscope} + \edef\msc@shape{ncondition shape} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@cond@star}{\msc@isstarfalse\msc@cond@star*} +} +% \ncondition(*)[options]{text}{instancelist} +\def\msc@cond@star*{ + \pgfutil@ifnextchar[{\msc@condition}{\msc@condition[]} +} +\newif\ifmsc@isfirst +\def\msc@condition[#1]#2#3{ + \mscset{inner sep=\mscget{label distance},#1} + \msc@isfirsttrue + \@for\msc@arg:=#3\do{% + \pgfkeysifdefined{/msc/instance/\msc@arg/no}{ + \ifmsc@isfirst%first instance in the list + \mscgetx{(msc@node\msc@arg @l0)}{\msc@minx} + \mscgetx{(msc@node\msc@arg @r0)}{\msc@maxx} + \mscgety{(msc@level\the\c@msclevelcnt)}{\msc@y} + \else + \mscgetx{(msc@node\msc@arg @r0)}{\msc@x} + \pgfmathparse{max(\msc@x,\msc@maxx)} + \edef\msc@maxx{\pgfmathresult pt} + \mscgetx{(msc@node\msc@arg @l0)}{\msc@x} + \pgfmathparse{min(\msc@x,\msc@minx)} + \edef\msc@minx{\pgfmathresult pt} + \fi + \msc@isfirstfalse + \xdef\msc@instname{\msc@arg} + }{ + \msc@instundefinederr{\msc@arg} + } + } + \ifmsc@isfirst \else%there are proper instances + \pgfmathparse{2*\mscget{condition overlap}+\msc@maxx-\msc@minx} + \edef\msc@width{\pgfmathresult pt} + \ifmsc@isstar + \def\msc@tempr{} + \else + %\msc@savebox{\parbox{\msc@width}{#2}} + \edef\msc@tempr{%text depth={\the\dp\msc@box}, + % text height={{\the\ht\msc@box+\the\dp\msc@box}}, + align=center, text width=\msc@width-2*\mscget{label distance},} + \fi + \def\aa{aeee} + \xdef\msc@tempb{[/msc, draw, anchor=north,shape=\msc@shape, + \msc@tempr + inner sep=\mscget{label distance}, + minimum height=\mscget{condition height}, + minimum width=\msc@width, + every condition,/tikz/line width=\mscget{line width}, #1](msc@condition@\the\c@condition) + at ({(\msc@maxx+\msc@minx)/2},\msc@y) {\unexpanded\expandafter{#2}}; + } + \fi + \end{pgfscope} + \adddraw{\msc@instname}{\the\c@msclevelcnt}{\expandafter\node\msc@tempb } + \@for\msc@args:=#3\do{% + \edef\msc@tempa{\noexpand\mscgety{(msc@condition@\the\c@condition.south)}{\noexpand\msc@y} + \noexpand\msc@setlastlevel{\msc@args}{\noexpand\msc@y}} +% \show\msc@tempa + \adddraw{\msc@args}{\the\c@msclevelcnt}{\msc@tempa} + } } -% -\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}}% - }% +% \order[side]{sender}{receiver}[level shift] +\def\order{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar[{\msc@order@opt}{\msc@order@opt[]} +} +\def\msc@order@opt[#1]{ + \ifx#1l \mscset{side=left} + \else \ifx#1r \mscset{side=right} + \else + \mscset{#1} + \def\msc@options{#1} + \fi + \fi + \pgfutil@ifnextchar[{\msc@order@opt}{\msc@order@noopt} +} +\def\msc@order@noopt#1#2{ + \xdef\msc@sender{#1} + \xdef\msc@receiver{#2} + \pgfutil@ifnextchar[{\msc@order}{\msc@order[\mscget{level shift}]} +} +\def\msc@order[#1]{ + \pgfkeysifdefined{/msc/instance/\msc@receiver/no}{ + \pgfkeysifdefined{/msc/instance/\msc@sender/no}{ + \msc@getlevel shift{#1}{\msc@level shift}{\msc@tempa} + \ifx\msc@sender\msc@receiver %self message + \IfStrEq{\mscget{side}}{left}{ + \def\msc@dir{l} + \edef\msc@dist{-\mscget{self message width}} + }{ + \def\msc@dir{r} + \edef\msc@dist{\mscget{self message width}} + } + \xdef\msc@tempb{[/msc, order loop={\msc@dist}, + every order, \msc@options] + (msc@node\msc@sender @\msc@dir\the\c@msclevelcnt) to + (msc@node\msc@receiver @\msc@dir\msc@level shift); + } + \else + \ifnum\mscget{instance/\msc@sender/no}\expandafter<\mscget{instance/\msc@receiver/no}\relax + \def\msc@ldir{r} + \def\msc@rdir{l} + \else + \def\msc@ldir{l} + \def\msc@rdir{r} + \fi + \xdef\msc@tempb{[/msc,order,every order,\msc@options] + (msc@node\msc@sender @\msc@ldir\the\c@msclevelcnt) to + (msc@node\msc@receiver @\msc@rdir\msc@level shift); + } + \fi + \end{pgfscope} + \addDdraw{\msc@sender}{\msc@receiver}{\msc@tempa}{\expandafter\draw\msc@tempb} + }{\msc@instundefinederr{\msc@sender}\end{pgfscope}} + }{\msc@instundefinederr{\msc@receiver}\end{pgfscope}} +} + +% update the lastlevel for a given instance +% #1 name of the instance +% #2 level number +\def\msc@updatelastlevel#1#2{ + \msc@StrEqEither{#1}{envright}{envleft} {}{ + \path let \p1 = (msc@lastlevel#1), \p2 = (msc@level#2) + in coordinate (msc@lastlevel#1) at (\x1,{min(\y1,\y2)}); } } -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% 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}} - }% - }% +% set the lastlevel for a given instance +% #1 name of the instance +% #2 new height +\def\msc@setlastlevel#1#2{ + \msc@StrEqEither{#1}{envright}{envleft} {}{ + \draw let \p1 = (msc@lastlevel#1) in coordinate (msc@lastlevel#1) + at (\x1,{min(\y1,#2)}); + } } -% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% MSC MARKS -% -% \mark[#1]{#2}{#3} -% #1: placement: tl,bl,tr,br -% #2: text -% #3: instance nick name +% CO-REGIONS % -\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}} - {%bl: - \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}} - {%tr: - \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}} - {%br: - \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} - }}}}} -} +% \coregionstart starts a coregion on instance #1 (nickname) in the current level. +\def\coregionstart{\pgfutil@ifnextchar[{\msc@coreg}{\msc@coreg[]}} +\def\msc@coreg[#1]#2{ + \regionstart[#1]{coregion}{#2}} +% \coregionend ends a coregion on instance #1 (nickname) in the current level. +\def\coregionend#1{\regionend{#1}}% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% MSC MEASURES -% +% REGIONS (normal, coregion, suspension, and activation) % -\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} +% define the begining of a region on the instance line +%\regionstart[options]{type}{instname} +% instance/#2/region/.initial=line, %possible % values:normal,coregion,suspension,activation +\def\regionstart{\pgfutil@ifnextchar[\msc@regionstart{\msc@regionstart[]}} +\def\msc@regionstart[#1]#2#3{ + \begin{pgfscope} + \mscset{#1} + \xdef\msc@tempa{\mscget{region width}} + \end{pgfscope} + \pgfkeysifdefined{/msc/instance/#3/no}{ + \msc@StrEqEither{\mscget{instance/#3/region}}{normal}{seminormal}{ + \msc@drawinstanceline{#2}{\the\c@msclevelcnt} + \IfEqCase{#2} {{coregion}{} {activation}{} {suspension}{}} + [\msc@unknownregionstyleerr{#2}] + \mscset{instance/#3/region={#2}, + instance/#3/region level/.expand once={\the\c@msclevelcnt}, + instance/#3/region width/.expand once=\msc@tempa}% + \msc@regbar{#3}{\the\c@msclevelcnt} + } + {msc@regionstartederr{#3}{\mscget{instance/#3/region}}} + } + {\msc@instundefinederr{#3}} +} +%helper function to draw region horizontal bar(s) +% #1 instname +% #2 level +\def\msc@regbar#1#2{ + \xdef\msc@temp@body{} + \edef\msc@region{\mscget{instance/#1/region}} + \pgfpointanchor{msc@level#2}{center} + \edef\msc@regbar@tempb{\the\pgf@y} + \pgfpointanchor{msc@lastlevel#1}{center} + \pgfmathparse{\msc@regbar@tempb-\the\pgf@y} + \ifnum0<\pgfmathresult\relax + \else + \IfStrEq{\mscget{instance/#1/type}}{fat}{ + \IfStrEq{\msc@region}{coregion}{ + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, every region,every + coregion] let \noexpand\p1=(msc@node#1@l#2) in + (\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) -- + (\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line + width}/2,\noexpand\y1); + \noexpand\draw [/msc,/tikz/line width=\mscget{line width}, every region,every + coregion] let \noexpand\p1=(msc@node#1@r#2) in + (\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) -- + (\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line width}/2,\noexpand\y1); } - {% right from instances - \setlength{\tmp@Xa}{\msc@instrxpos{#3}} - \setlength{\tmp@Xb}{\msc@instrxpos{#4}} - \setlength{\tmp@X}{\tmp@Xb + \msc@measuredist} + }{ + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, every region,every \msc@region] let + \noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@node#1@r#2) in + (\noexpand\x1-\mscget{line width}/2,\noexpand\y1)--(\noexpand\x2+\mscget{line width}/2,\noexpand\y2); } } - {% - \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} + }{ + \IfStrEq{\msc@region}{coregion}{ + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, every region,every coregion] let + \noexpand\p1=(msc@node#1@l#2) in + (\noexpand\x1-\mscget{instance/#1/region width}/2-\mscget{line width}/2,\noexpand\y1) -- + (\noexpand\x1+\mscget{instance/#1/region width}/2+\mscget{line width}/2,\noexpand\y1); } - {% right from instances - \setlength{\tmp@Xa}{\msc@instrxpos{#3}} - \setlength{\tmp@Xb}{\msc@instrxpos{#4}} - \setlength{\tmp@X}{\tmp@Xa + \msc@measuredist} + }{ + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, every region, every \msc@region] + let + \noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@node#1@r#2) in + (\noexpand\x1-\mscget{line width}/2,\noexpand\y1)--(\noexpand\x2+\mscget{line width}/2,\noexpand\y2); } } - \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} - } + } +% \show\msc@temp@body + \adddraw{#1}{\the\c@msclevelcnt}{\expandafter\path\msc@temp@body} + \adddraw{#1}{\the\c@msclevelcnt}{\mscgety{(msc@lastlevel#1)}{\msc@yo}\msc@setlastlevel{#1}{\msc@yo-\mscget{line width}/2}} + \fi } -% -% -% \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} +% draw the instance line with the region +% #1 instname +% #2 level +\def\msc@regbody#1#2{ + \xdef\msc@temp@body{;} + \pgfpointanchor{msc@level#2}{center} + \edef\msc@regbody@tempb{\the\pgf@y} + \pgfpointanchor{msc@lastlevel#1}{center} + \pgfmathparse{\msc@regbody@tempb-\the\pgf@y} + \ifnum0<\pgfmathresult\relax + \else + \IfEqCase{\mscget{instance/#1/region}}{ + {coregion}{ + \IfStrEq{\mscget{instance/#1/type}}{fat}{ + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, mscdash, every region, every coregion] + let \noexpand\noexpand\noexpand\p1=(msc@node#1@r#2), \noexpand\noexpand\noexpand\p2=(msc@lastlevel#1) in + (\noexpand\noexpand\noexpand\x1,\noexpand\noexpand\noexpand\y2)-- + (\noexpand\noexpand\noexpand\x1,{min(\noexpand\noexpand\noexpand\y2,\noexpand\noexpand\noexpand\y1)}); + } + }{\xdef\msc@temp@body{;}} + \xdef\msc@temp@body{ + [/msc,/tikz/line width=\mscget{line width}, draw, mscdash, every region, every coregion] + let \noexpand\p1=(msc@node#1@l#2), \noexpand\p2=(msc@lastlevel#1) in + (\noexpand\x1,\noexpand\y2)--(\noexpand\x1,{min(\noexpand\y2,\noexpand\y1)});\noexpand\path\msc@temp@body + } + }% + {activation}{ + \xdef\msc@temp@body{ + [/msc,fill=lightgray,/tikz/line width=\mscget{line width},every region, every activation] + (msc@node#1@l#2|-msc@lastlevel#1) rectangle(msc@node#1@r#2); + \noexpand\draw[/msc,/tikz/line width=\mscget{line width},every region, every activation] + (msc@node#1@l#2) -- (msc@node#1@l#2|-msc@lastlevel#1) + (msc@node#1@r#2) -- (msc@node#1@r#2|-msc@lastlevel#1); + } + }% + {suspension}{ + \xdef\msc@temp@body{ + [/msc,draw,suspension dash, + /tikz/line width=\mscget{line width},every region, every activation] + (msc@node#1@r#2)--(msc@node#1@r#2|-msc@lastlevel#1) + (msc@node#1@l#2)--(msc@node#1@l#2|-msc@lastlevel#1); + } + }% + }[] + \adddraw{#1}{\the\c@msclevelcnt}{\expandafter\path\msc@temp@body} + \fi } -% -% -\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}% +% define the end of region +%\regionend{instname} +\def\regionend#1{ + \pgfkeysifdefined{/msc/instance/#1/no}{ + \edef\msc@region{\mscget{instance/#1/region}} + \IfStrEq{\msc@region}{normal}{ + \msc@regionnotstartederr{#1} + } + \msc@regbody{#1}{\the\c@msclevelcnt} + \msc@regbar{#1}{\mscget{instance/#1/region level}} + \msc@regbar{#1}{\the\c@msclevelcnt} + \adddraw{#1}{\the\c@msclevelcnt}{\msc@updatelastlevel{#1}{\the\c@msclevelcnt}} + \msc@StrEqEither{\msc@region}{suspension}{activation}{ + \mscset{instance/#1/region=seminormal} + }{\mscset{instance/#1/region=normal}} + } + { + \msc@instundefinederr{#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}} +%macro stores first character in \msc@fst and last character in \msc@lst +\def\msc@fl#1{\msc@flx#1\empty\empty\empty} +\def\msc@flx#1#2#3\empty{% +\edef\msc@fst{#1}% + \edef\msc@cdar{#2}% + \edef\msc@cddr{#3}% + \ifx\msc@cddr\empty + \let\msc@lst\msc@cdar + \else + \expandafter\msc@flxx + \fi + #3} +\def\msc@flxx#1#2\empty{% + \edef\msc@car{#1}% + \ifx\msc@car\empty + \else + \let\msc@lst\msc@car + \expandafter\msc@flxx + \fi + #2\empty} +%\referencestart[options][lo][ro]{nickname}{text}{leftinstance}{rightinstance} +\def\referencestart{ + \begin{pgfscope}\gdef\msc@options{} + \pgfutil@ifnextchar[\msc@refstartlo{\msc@refstartloro}} +\def\msc@refstartloro{ + \edef\msc@lo{\mscget{left reference overlap}} + \edef\msc@ro{\mscget{right reference overlap}} + \msc@refstart +} +\def\msc@refstartlo[#1]{ + \expandafter\expandafter\expandafter\msc@fl\expandafter{#1} + \msc@caseFiveEither{\msc@fst}{1}{2}{3}{4}{5}{ + \edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]} + }{ + \msc@caseFiveEither{\msc@fst}{6}{7}{8}{9}{0}{ + \edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]} + }{ + \msc@StrEqEither{\msc@fst}{-}{.}{ + \edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@refstartro{\msc@refstartro[\mscget{right reference overlap}]} + }{ + \mscset{#1} + \xdef\msc@options{#1} + \pgfutil@ifnextchar[\msc@refstartlo{\msc@refstartloro} + } } - {% 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}} + } +} +\def\msc@refstartro[#1]{ + \edef\msc@ro{#1}\msc@refstart +} +\def\msc@refstart#1#2#3#4{ + \pgfkeysifdefined{/msc/instance/#3/no}{ + \pgfkeysifdefined{/msc/instance/#4/no}{ + \path[draw] (msc@level\the\c@msclevelcnt-|msc@node#3@l0) ++(-\msc@lo,0) coordinate + (msc@node#1left) + (msc@level\the\c@msclevelcnt-|msc@node#4@r0) ++(\msc@ro,0) coordinate + (msc@node#1right); + \end{pgfscope} + \msc@cover{#3}{#4}{+} + \mscset{ + reference/#1/options/.style/.expanded=\msc@options, + reference/#1/left/.initial=#3, + reference/#1/text/.initial={#2}, + reference/#1/right/.initial=#4 + } + }{ + \end{pgfscope}\msc@instundefinederr{#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}% + }{ + \end{pgfscope}\msc@instundefinederr{#3} + } } -% -\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}% +\def\msc@cover#1#2#3{ + \pgfmathparse{\mscget{instance/#2/cover} #3 1} + \mscset{instance/#2/cover/.expand once=\pgfmathresult} + \IfStrEq{#1}{#2}{}{ + \ifnum0<\mscget{instance/\msc@inst@name/no} + \msc@previousinstance{#2} + \msc@cover{#1}{\msc@inst@name}{#3} + \msc@regbody{\msc@inst@name}{\the\c@msclevelcnt} + \else + \fi + } } -% -\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}} +\def\referenceend#1{ + \pgfkeysifdefined{/msc/reference/#1/left}{%calculating framearch + \mscgetx{(msc@node#1left)}{\msc@xa} + \mscgetx{(msc@node#1right)}{\msc@xb} + \mscgety{(msc@node#1left)}{\msc@yb} + \mscgety{(msc@level\the\c@msclevelcnt)}{\msc@ya} + \pgfmathparse{0.25/2 *min(\msc@xb-\msc@xa,\msc@yb-\msc@ya)} + \edef\msc@tempa{\pgfmathresult} + \msc@cover{\mscget{reference/#1/left}}{\mscget{reference/#1/right}}{-} + \node[/msc,fit={(msc@node#1left) (msc@node#1right) + (msc@node#1right|-msc@level\the\c@msclevelcnt)}, + draw,rectangle, rounded corners=\msc@tempa pt, inner sep=0,/tikz/line + width=\mscget{line width},every reference, + /msc/reference/#1/options + ]{\mscget{reference/#1/text}}; + }{ + \msc@refundefinederr{#1} + } +} +%\inlinestart[options][lo][ro]{nickname}{text}{leftinstance}{rightinstance} +\def\inlinestart{ + \begin{pgfscope} + \gdef\msc@options{} + \pgfutil@ifnextchar[\msc@inlstartlo{\msc@inlstartloro} +} +\def\msc@inlstartloro{ + \edef\msc@lo{\mscget{left inline overlap}} + \edef\msc@ro{\mscget{right inline overlap}} + \msc@inlstart +} + +\def\msc@inlstartlo[#1]{ + \expandafter\expandafter\expandafter\msc@fl\expandafter{#1} + \msc@caseFiveEither{\msc@fst}{1}{2}{3}{4}{5}{ + \edef\msc@lo{#1} + \pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]} + }{ + \msc@caseFiveEither{\msc@fst}{6}{7}{8}{9}{0}{ + \edef\msc@lo{#1} \pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]} + }{ + \msc@StrEqEither{\msc@fst}{-}{.}{ + \edef\msc@lo{#1} + \pgfutil@ifnextchar[\msc@inlstartro{\msc@inlstartro[\mscget{right inline overlap}]} + }{ + \mscset{#1} + \xdef\msc@options{#1} + \pgfutil@ifnextchar[\msc@inlstartlo{\msc@inlstartloro} + } + } + } +} +\def\msc@inlstartro[#1]{ + \edef\msc@ro{#1}\msc@inlstart +} +%msc@inlstart{nickname}{text}{leftinstance}{rightinstance} +\def\msc@inlstart#1#2#3#4{ + \pgfkeysifdefined{/msc/instance/#3/no}{ + \pgfkeysifdefined{/msc/instance/#4/no}{ + \path[draw] (msc@level\the\c@msclevelcnt-|msc@node#3@l0) ++(-\msc@lo,0) coordinate + (msc@node#1left) + (msc@level\the\c@msclevelcnt-|msc@node#4@r0) ++(\msc@ro,0) coordinate + (msc@node#1right); + \end{pgfscope} + \mscset{ + inline/#1/options/.style/.expanded=\msc@options, + inline/#1/left/.initial={#3}, + inline/#1/text/.initial={#2} + } + }{ + \end{pgfscope}\msc@instundefinederr{#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}} + }{ + \end{pgfscope}\msc@instundefinederr{#3} + } +} +%\inlineseparator[options]{nickname} +\def\inlineseparator{ + \begin{pgfscope} + \pgfutil@ifnextchar[\msc@inlseparator{\msc@inlseparator[]} +} +\def\msc@inlseparator[#1]#2{ + \pgfkeysifdefined{/msc/inline/#2/left}{ + \mscset{#1} + \end{pgfscope} + \path[/msc,draw, mscdash, + /tikz/line width=\mscget{line width}, + dash phase=2pt, + every inline,inline/#2/options,#1] + (msc@node#2left|-msc@level\the\c@msclevelcnt)--(msc@node#2right|-msc@level\the\c@msclevelcnt); + }{ + \msc@inlundefinederr{#2} + \end{pgfscope} + } +} +%\inlineend{nickname} +\def\inlineend{ + \pgfutil@ifnextchar*{\msc@isstartrue\msc@inlineend}{\msc@isstarfalse\msc@inlineend*} +} +\def\msc@inlineend*#1{ + \pgfkeysifdefined{/msc/inline/#1/text}{ + \path[/msc,draw, + /tikz/line width=\mscget{line width}, + every inline,inline/#1/options] + (msc@node#1left) node[/msc,draw,chamfered rectangle, + chamfered rectangle corners=south east, + chamfered rectangle xsep=\mscget{label distance}/2, + chamfered rectangle ysep=\mscget{label distance}/2, + inner sep=\mscget{label distance}/4, + xshift=-\mscget{line width}/2, yshift=\mscget{line width}/2, + anchor=north west,inline/#1/options](a) + {\mscget{inline/#1/text}} + (msc@node#1left|-msc@level\the\c@msclevelcnt)++(0,-\mscget{line width}/2) + --(msc@node#1left)--(msc@node#1right)-- + (msc@node#1right|-msc@level\the\c@msclevelcnt)--++(0,-\mscget{line width}/2); + \ifmsc@isstar + \inlineseparator{#1} + \else + \inlineseparator[solid]{#1} + \fi + }{ + \msc@refundefinederr{#1} + } +} +%\gate(*)[options][hpos][vpos]{gatename}{instname} +\def\gate{ + \begin{pgfscope} + \def\msc@options{} + \pgfutil@ifnextchar*{\msc@isstartrue\msc@gate@star}{\msc@isstarfalse\msc@gate@star*} +} +\def\msc@gate@star*{ + \pgfutil@ifnextchar[{\msc@gate@opt}{\msc@gate@opt[]} +} +\def\msc@gate@opt[#1]{ + \IfStrEq{#1}{l}{\mscset{side=left} \pgfutil@ifnextchar[\msc@gate{\msc@gate[]} + }{ + \IfStrEq{#1}{r}{\mscset{side=right}\pgfutil@ifnextchar[\msc@gate{\msc@gate[]} + }{ + \mscset{#1} + \def\msc@options{#1} + \pgfutil@ifnextchar[\msc@gate@opt{\msc@gate[]} } - \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}% +\def\msc@gate[#1]#2#3{ + \def\msc@undefined{false} + \ifx#1c \mscset{position=mid} \else + \ifx#1b \mscset{position=below} \else + \ifx#1t \mscset{position=above} \fi \fi \fi + \pgfkeysifdefined{/msc/instance/#3/no}{%instance name + \IfStrEq{\mscget{side}}{left}{ + \edef\msc@node{msc@node#3@l\the\c@msclevelcnt} + }{ + \edef\msc@node{msc@node#3@r\the\c@msclevelcnt} + } + }{ + \pgfutil@ifundefined{pgf@sh@ns@msc@node#3}{% neither instance name nor reference node + \def\msc@undefined{true} + \msc@instundefinederr{#3} + } + { + \edef\msc@node{msc@node#3|-msc@level\the\c@msclevelcnt} + } } + \IfStrEq{\msc@undefined}{false}{ + \ifmsc@isstar + \xdef\msc@tempb{[fill,\msc@options] (\msc@node) + node[\mscget{position} + \mscget{side}]{\unexpanded\expandafter{#2}} circle (\mscget{gate symbol radius});} + \edef\msc@tempa{\noexpand\noexpand\noexpand\path[fill,line width=0pt](\msc@node) circle (\mscget{gate symbol radius});} + \else + \xdef\msc@tempb{[\msc@options] (\msc@node) node[\mscget{position} \mscget{side}]{\unexpanded\expandafter{#2}};} + \fi + }{} + \end{pgfscope} + \adddraw{#3}{\the\c@msclevelcnt}{\expandafter\path\msc@tempb} +} + +\def\inststop{\stop*}%old name of command +%\stop(*)[options]{instancename} +\def\stop{\pgfutil@ifnextchar*{\msc@isstartrue\msc@stop@nostar}{\msc@isstarfalse\msc@stop@nostar*}} +\def\msc@stop@nostar*{\pgfutil@ifnextchar[\msc@stop{\msc@stop[]}} +\def\msc@stop[#1]#2{ + \pgfkeysifdefined{/msc/instance/#2/no}{ + \IfStrEq{on}{\mscget{instance/#2/status}}{ + \msc@global@set{instance/#2/status=off} + \begin{pgfscope} + \mscset{#1} + \ifmsc@isstar \mscset{instance end=foot} \fi + \IfStrEq{\mscget{instance end}}{foot}{ + \xdef\msc@tempb{[/msc,fill=\mscget{draw foot},/tikz/line width=\mscget{line width}, every instance foot,#1] + (msc@lastlevel#2-|msc@node#2.east) + ++(0,-\mscget{foot height}) rectangle + (msc@lastlevel#2-|msc@node#2.west) + (msc@lastlevel#2-|msc@node#2.south) + ++(0,-\mscget{foot height}) + coordinate (msc@foot#2); + } + }{ + \xdef\msc@tempb{[/msc,draw=\mscget{draw foot}, /tikz/line width=\mscget{line width}, + every instance foot,#1] + (msc@node#2@l\the\c@msclevelcnt) ++(-\mscget{line width}/2,0)-- + ($(msc@node#2@l\the\c@msclevelcnt)!0.5!(msc@node#2@r\the\c@msclevelcnt)$) + coordinate (msc@foot#2) + ++(\mscget{stop width}/2,\mscget{stop width}/2) + -- ++(-\mscget{stop width},-\mscget{stop width}) + ++(0,\mscget{stop width}) + -- ++(\mscget{stop width},-\mscget{stop width}) + ++(-\mscget{stop width}/2,\mscget{stop width}/2) + -- (msc@node#2@r\the\c@msclevelcnt) + --++(\mscget{line width}/2,0); + } + } + \end{pgfscope} + \adddraw{#2}{\the\c@msclevelcnt}{\expandafter\path\msc@tempb} + }{} + }{\msc@instundefinederr{#2}} } -% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% \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\mscunit{cm}% \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{\setmsckeyword}[1]{\mscset{/msc/msc keyword={#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}} - +\newcommand{\drawframe}[1]{\IfStrEq{#1}{yes}{\mscset{draw frame=}}{\IfStrEq{#1}{no}{\mscset{draw frame=none}}{}}}% +\newcommand{\drawinsthead}[1]{\IfStrEq{#1}{yes}{\mscset{draw head=}}{\IfStrEq{#1}{no}{\mscset{draw head=none}}{}}} +\newcommand{\drawinstfoot}[1]{\IfStrEq{#1}{yes}{\mscset{draw foot=}}{\IfStrEq{#1}{no}{\mscset{draw foot=none}}{}}} +\newcommand{\showgrid}{\mscset{draw grid}} +\newcommand{\nogrid}{\mscset{draw grid={none}}} +\newcommand{\setmscscale}[1]{\mscset{msc scale=#1}}% +\newcommand{\messarrowscale}[1]{\mscset{arrow scale=#1}}% -\def\msc@settitle{% -\MSC@settitle{msc}% - {0\mscunit}% - {-\msc@totalheight}% - {\msc@totalwidth}% - {0\mscunit}% - {\msc@titlejustification}% - {\msckeywordstyle{\msckeyword}{} \msc@title}% -} +%\mscset but globally +\def\msc@global@set#1{\globaldefs=1\relax\mscset{#1}\globaldefs=0\relax}% -% -% \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}\mbox{% - \psscalebox{\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}}% +% \begin{msc}[options][headerpos]{mscname} +% ...definition of the MSC... +% \end{msc} +%\regionend{instname} +\def\msc{% + \pgfutil@ifnextchar[\msc@mscopt{\msc@mscopt[l]} +} +\def\msc@mscopt[#1]{% + % \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 + \ifx#1l + \mscset{title position=left} + \else \ifx#1c + \mscset{title position=center} + \else \ifx#1r + \mscset{title position=right} + \else + \pgfutil@ifundefined{msc@tikzstarted} + { + \tikzpicture[/msc,#1]% + \def\msc@tikzstarted{}}% + { + \relax} + \fi + \fi + \fi + \pgfutil@ifnextchar[{\msc@mscopt}{\msc@mscnoopt} +} +% core of msc with options parsed - +\def\msc@mscnoopt#1{% parse name + % #1: mscname + \pgfutil@ifundefined{msc@tikzstarted} + { + \tikzpicture\def\msc@tikzstarted{}% }% - {\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}% + {\relax} + % Options handling ends here + \c@mscinstcnt 0\relax% initialize number of instances to 0 + \c@condition 0\relax% initialize number of condition to 0 + \c@msclevelcnt 1\relax% initialize level to 1 + \gdef\c@maxlevelcnt{0}% initialize maximum encountered level to 0 +% \msc@global@set{ +% } + \mscset{ + /tikz/scale/.expanded=\mscget{msc scale}, + /tikz/every node/.style/.expanded={scale/.expanded=\mscget{msc scale}}, + instance/envleft/no/.initial=0, + instance/envright/no/.initial=1, + instanceno/0/name/.initial=envleft,% + instanceno/1/name/.initial=envright, + instance/envleft/type/.initial=environment, + instance/envright/type/.initial=environment, + instance/envleft/region/.initial=normal, + instance/envright/region/.initial=normal, + instance/envleft/status/.initial=on, + instance/envright/status/.initial=on, + /msc/msc/name/.initial={#1} + } + \pgfmathparse{0-\mscget{head top distance} - \mscget{head height}} + \xdef\msc@tempa{\pgfmathresult} + \coordinate (msc@level0) at (0,\msc@tempa pt); + \coordinate (msc@nodeenvright) at (0,\msc@tempa pt); + \coordinate (msc@nodeenvleft) at (0,\msc@tempa pt); + \coordinate (msc@footenvleft) at (msc@nodeenvleft); + \coordinate[below=\mscget{first level height} of msc@level0] (msc@level1); +} +\def\msc@drawgrid{ + \begin{pgfonlayer}{background} + \pgfpointanchor{current bounding box}{south west} + \pgfmathparse{ceil(\pgf@x/\pgf@xx)}%pgf@xx stores 1 of current unit (e.g. 1cm) + \edef\msg@xa{\pgfmathresult}% + \pgfmathparse{ceil(\pgf@y/\pgf@yy)}% + \edef\msg@ya{\pgfmathresult}% + \pgfpointanchor{current bounding box}{north east} + \pgfmathparse{floor(\pgf@x/\pgf@xx)}% + \edef\msg@xb{\pgfmathresult}% + \pgfmathparse{floor(\pgf@y/\pgf@yy)}% + \edef\msg@yb{\pgfmathresult}% + \path (\msg@xa,\msg@ya) to[/msc/\mscget{draw grid}](\msg@xb,\msg@yb); + \end{pgfonlayer} +} +%\def\endmsc[options] +\def\endmsc{% +% \let\setlength\msc@OrigSL + \pgfutil@ifnextchar[\msc@endmsc{\msc@endmsc[]} + \endtikzpicture + \global\let\msc@tikzstarted\relax +} +\def\msc@endmsc[#1]{ + \begin{pgfscope} + \mscset{#1} + \ifnum0<\c@mscinstcnt\relax + \ifnum\c@msclevelcnt<\c@maxlevelcnt\relax + \pgfmathparse{\c@maxlevelcnt-\the\c@msclevelcnt} + \pgfkeys{/pgf/number format/precision=0} + \pgfmathroundto{\pgfmathresult} + \nextlevel[\pgfmathresult]%add missing levels + \fi + \mscset{level height=\mscget{last level height}} + \nextlevel %add last but one level + \foreach \msc@tempa in {1,...,\c@mscinstcnt} {% + \stop[instance end=foot,#1]{\mscget{instanceno/\msc@tempa/name}} + } + \nextlevel %add last level just to draw outstanding foots + \else + \coordinate (msc@footenvleft) at (msc@nodeenvright); + \coordinate[below=\mscget{first level height} of msc@level0] (msc@level1); + \fi + \msc@drawenvironment + \IfStrEq{none}{\mscget{draw grid}}{}{%we draw help grid + \msc@drawgrid + } + \end{pgfscope} +} +\def\msc@drawenvironment{ + \path[line width=\mscget{line width}] + let \p1=(msc@node\mscget{instanceno/1/name}.north), + \p2=(msc@foot\mscget{instanceno/\the\c@mscinstcnt/name}.south), + \p3=(current bounding box.south east), + \p4=(current bounding box.north west) in + ({\x2+max(\mscget{right environment distance},\x3-\x2)}, + {\y2+min(-\mscget{foot distance},\y3-\y2)}) coordinate(msc@env@se) [draw=\mscget{draw frame}] rectangle + ({\x1+min(-\mscget{left environment distance},\x4-\x1)}, + {\y1+max(\mscget{head top distance},\y4-\y1)}) coordinate(msc@env@nw); + \path let \p1=(msc@env@nw), + \p2=(msc@env@se) in + (\x1,\y1) +(\mscget{title distance},-\mscget{title top distance}) + node[rectangle, anchor=north west, inner sep=0, align=\mscget{title + position}, text + width=(\x2-\x1)-2*\mscget{title distance}] + {\msckeywordstyle{\mscget{msc keyword}} \mscget{msc/name}}; + \foreach \msc@tempa in {0,...,\c@msclevelcnt} {%create nodes for environment + \path let \p1=(msc@env@se), + \p2=(msc@env@nw), + \p3=(msc@level\msc@tempa) in + (\x2,\y3) coordinate[name=msc@nodeenvleft@r\msc@tempa, + alias=msc@nodeenvleft@l\msc@tempa] -- + (\x1,\y3) coordinate[name=msc@nodeenvright@l\msc@tempa, + alias=msc@nodeenvright@r\msc@tempa]; + } + \pgfkeysifdefined{/msc/levelenv/havedraw}{ +% \tikzset{/msc/levelenv/draw/.show code} + \mscset{/msc/levelenv/draw} + \msc@global@set{/msc/levelenv/draw/.code={}} + }{} } - -\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{)}% +% \setmscvalues assigns compatible values to all msc-parameters +% Currently, three sets of values are supported: large, normal +% and small. +\def\setmscvalues#1{% + \IfEqCase{#1}{% + {large}{\mscset{#1 values}}% + {normal}{\mscset{#1 values}}% + {small}{\mscset{#1 values}}% + }[\msc@unknownmscvalueserr{#1}] } - % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % 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}} +\def\msckeywordstyle#1{\textbf{#1}} +\newcommand{\sethmsckeyword}[1]{\mscset{/msc/hmsc keyword={#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}% +% \begin{hmsc}[headerpos]{hmscname}(llx,lly)(urx,ury) +\def\hmsc{\def\msc@key{hmsc} \pgfutil@ifnextchar[\msc@hmscopt{\msc@hmscopt[]}} +\def\msc@hmscopt[#1]{% + \msc@global@set{/msc/draw code/.code={}} + \ifx#1l + \mscset{title position=left} + \else \ifx#1c + \mscset{title position=center} + \else \ifx#1r + \mscset{title position=right} + \else + \pgfutil@ifundefined{msc@tikzstarted}{ + \tikzpicture[#1]% + \def\msc@tikzstarted{} + }{\relax} + \fi + \fi \fi - \next% + \pgfutil@ifnextchar[{\msc@hmscopt}{\msc@hmscnoopt} +} + +\def\msc@hmscnoopt#1{% + % #1: mscname + \pgfutil@ifundefined{msc@tikzstarted}{ + \tikzpicture\def\msc@tikzstarted{}% + }{\relax} + \mscset{ + /tikz/scale/.expanded=\mscget{msc scale}, + /tikz/every node/.style/.expanded={scale/.expanded=\mscget{msc scale}}, + /msc/\msc@key/name/.initial={#1}} + \pgfutil@ifnextchar({\msc@hmsc}{} +} + +\def\msc@hmsc(#1,#2)(#3,#4){ + \path (#1,#4) coordinate(msc@\msc@key @nw) + (#3,#2) coordinate(msc@\msc@key @se); +} +%\end{hmsc}[options] +\def\endhmsc{\def\msc@key{hmsc}\pgfutil@ifnextchar[\msc@endhmsc{\msc@endhmsc[]} + \endtikzpicture + \global\let\msc@tikzstarted\relax +} +\def\msc@endhmsc[#1]{ + \begin{pgfscope} + \mscset{#1} + \pgfutil@ifundefined{pgf@sh@ns@msc@\msc@key @nw}{%use bounding box + \path (current bounding box.north west) + ++(-\mscget{west \msc@key\space margin}, + \mscget{north \msc@key\space margin}+\mscget{title top distance}+\heightof{\mscget{msc@key/name}}+\depthof{\mscget{\msc@key/name}}) + coordinate(msc@\msc@key @nw) (current bounding box.south east) + ++(\mscget{east \msc@key\space margin},-\mscget{south \msc@key\space margin}) + coordinate(msc@\msc@key @se); + }{} + \IfStrEq{\mscget{title position}}{left}{% + \path (msc@\msc@key @nw) +(\mscget{title distance},-\mscget{title top distance}) + node[anchor=north west,inner sep=0] + {\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}}; + }{ + \IfStrEq{\mscget{title position}}{center}{% + \path let \p1=(msc@\msc@key @nw), + \p2=(msc@\msc@key @se) in + (\x1/2+\x2/2,\y1) +(0,-\mscget{title top distance}) + node[anchor=north,inner sep=0] + {\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}}; + }{ + \IfStrEq{\mscget{title position}}{right}{% + \path let \p1=(msc@\msc@key @nw), + \p2=(msc@\msc@key @se) in + (\x2,\y1) +(-\mscget{title distance},-\mscget{title top distance}) + node[anchor=north east,inner sep=0] + {\msckeywordstyle{\mscget{\msc@key\space keyword}} \mscget{\msc@key/name}}; + }{} + } + } + \path[draw=\mscget{draw frame},line width=\mscget{line width}] (msc@\msc@key @nw)|-(msc@\msc@key @se)|-(msc@\msc@key @nw); + \IfStrEq{none}{\mscget{draw grid}}{}{%we draw help grid + \msc@drawgrid + } + \end{pgfscope} + \mscset{/msc/draw code} + \msc@global@set{/msc/draw code/.code={}} +} +%\hmscstartsymbol{nickname}(x,y) +\def\hmscstartsymbol{ + \edef\msc@nodetype{start symbol} + \pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]} +} +\def\msc@nodenotext[#1]#2{ + \edef\msc@options{#1} \edef\msc@name{#2}\def\msc@text{} + \pgfutil@ifnextchar({\msc@nodeAt}{ + \edef\msc@tempb{[/msc,\msc@nodetype,#1](\msc@name){};} + \expandafter\node\msc@tempb + } } - -% 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}% +\def\msc@nodetext[#1]#2#3{ + \edef\msc@options{#1} \edef\msc@name{#2}\def\msc@text{#3} + \pgfutil@ifnextchar({\msc@nodeAt}{ + \def\msc@tempb{[/msc,\msc@nodetype,#1](#2){#3};} + \expandafter\node\msc@tempb + } } - -% 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}% +\def\msc@nodeAt(#1,#2){ + \edef\msc@tempb{[/msc,\msc@nodetype,\msc@options](\msc@name) at (#1,#2) {\unexpanded\expandafter{\msc@text}};} + \expandafter\node\msc@tempb } - -% 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}}}% +%\hmscendsymbol{nickname}(x,y) +\def\hmscendsymbol{ + \edef\msc@nodetype{end symbol} + \pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]} } - -% 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}}}% +%\hmscreference{nickname}{text}(x,y) +\def\hmscreference{ + \edef\msc@nodetype{reference} + \pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]} } - -% 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}}}% +%\hmsc condition{nickname}{text}(x,y) +\def\hmsccondition{ + \edef\msc@nodetype{condition} + \pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]} } - - - -% 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{->}% +%\hmscconnection{nickname}(x,y) +\def\hmscconnection{ + \edef\msc@nodetype{connection} + \pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]} } - - - -% 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% -% }% +%\arrow{from-nickname}[coord-list]{to-n +\def\arrow{\pgfutil@ifnextchar[\msc@arrowopt{\msc@arrowopt[]}} +\def\msc@arrowopt[#1]#2{ + \def\msc@options{#1} + \edef\msc@node{#2} + \edef\msc@tempa{} + \pgfutil@ifnextchar[\msc@arrowgetpath{\msc@arrow} } - -\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}% +\def\msc@arrowgetpath[#1]{ + \StrSubstitute{#1}{(}{--(}[\msc@tempa] + \msc@arrow +} +\def\msc@arrow#1{ + \edef\msc@tempb{[/msc,/tikz/line width=\mscget{line width},arrow style,\msc@options] (\msc@node)\msc@tempa--(#1);} + \expandafter\draw\msc@tempb } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% Initialisation of the msc package +% MSC documents % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% -% \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} +% \mscdockeyword is the keyword representation of msc +\def\mscdockeywordstyle#1{\textbf{#1}} +\newcommand{\setmscdockeyword}[1]{\mscset{/msc/mscdoc keyword/.initial=mscdoc}} +\newcommand{\setmscdockeywordstyle}[1]{\def\mscdockeywordstyle{#1}}% + +%\begin{mscdoc}[headerpos]{mscdocname}(llx,lly)(urx,ury) +\def\mscdoc{\edef\msc@key{mscdoc} \pgfutil@ifnextchar[\msc@hmscopt{\msc@hmscopt[]}} +%\end{mscdoc}[options] +\def\endmscdoc{\edef\msc@key{mscdoc} + \pgfutil@ifnextchar[\msc@endhmsc{\msc@endhmsc[]} + \endtikzpicture + \global\let\msc@tikzstarted\relax +} +%\hmscreference{nickname}{text}(x,y) +\def\reference{\pgfutil@ifnextchar[\msc@nodenoname{\msc@nodenoname[]}} +\def\msc@nodenoname[#1]#2{ + \edef\msc@options{#1} \def\msc@text{#2} + \pgfutil@ifnextchar({\msc@nodenonameAt}{ + \edef\msc@tempb{[/msc,reference,#1](\msc@name){\unexpanded\expandafter{\msc@text}};} + \expandafter\node\msc@tempb + } } -% -% -% \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} +\def\msc@nodenonameAt(#1,#2){ + \edef\msc@tempb{[/msc,reference,every reference,\msc@options] at (#1,#2) {\unexpanded\expandafter{\msc@text}};} + \expandafter\node\msc@tempb } -% -% \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}}}}}% +\def\separator{\pgfutil@ifnextchar[\msc@separator{\msc@separator[]}} +\def\msc@separator[#1]#2{ + \begin{pgfscope} + \mscset{#1} + \xdef\msc@tempb{[/msc,/tikz/line width=\mscget{line width},mscdash] + let \noexpand\p1=(msc@mscdoc@nw), \noexpand\p2=(msc@mscdoc@se) in + (\noexpand\x1,#2)--(\noexpand\x2,#2);} + \end{pgfscope} + \mscset{/msc/draw code/.append code/.expand once={\expandafter\draw\msc@tempb}} } -% -% initialisation of the msc-parameters -\setmscvalues{normal} -\setfootcolor{black} + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Error and help messages @@ -2989,7 +2986,28 @@ but the nickname is already assigned to another msc object.\MessageBreak press to continue (the new msc object will be ignored).}% } -% +%instance already started +\gdef\msc@instancestarted#1{% + \PackageError{msc}{% error message + instance #1 is already active}{% help text + You tried to create instance '#1' but this instance is \MessageBreak + already active. Maybe try to stop it using "stop" command .\MessageBreak + press to continue.}% +} +% no such msc reference error +\gdef\msc@refundefinederr#1{% + \PackageError{msc}{% error message + undefined reference with nickname: #1}{% help text + You used '#1' as an reference nickname, but\MessageBreak + there is no reference with that nickname.}% +} +% no such msc reference error +\gdef\msc@inlundefinederr#1{% + \PackageError{msc}{% error message + undefined inline with nickname: #1}{% help text + You used '#1' as an inline nickname, but\MessageBreak + there is no inline with that nickname.}% +} % no such msc instance error \gdef\msc@instundefinederr#1{% \PackageError{msc}{% error message @@ -2997,39 +3015,39 @@ 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{% +% level height is not a positive integer +\gdef\msc@notpositiveintegerwarn#1#2{% + \PackageWarning{msc}{% error message + parameter #1.#2 is a float when integer was expected - + recovering by advancing by #1+1 levels where last level is scaled by 0.#2} +} +\gdef\msc@notpositiveintegererr#1{% \PackageError{msc}{% error message - unknown linestyle: #1}{% help text - Known msc linestyles are "solid", "dashed", and "dotted".\MessageBreak - You used '#1'.}% + Could not parse as number: #1}{% help text + The nextlevel should be a positive integer but instead #1 was given.}% } -% + % 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 + Known msc region styles are "coregion", "suspension", and "activation".\MessageBreak You used '#1'.}% } -% -% unknown self message label position error -\gdef\msc@unknownselfmessposerr#1{% +% region not started error +\gdef\msc@regionnotstartederr#1{% \PackageError{msc}{% error message - unknown position for self message: #1}{% help text - Known positions are "l" (left), "r" (right).\MessageBreak - You used '#1'.}% + no region is started for the instance "#1"}{% help text + You tried to end a region for the instance "#1", \MessageBreak + but no region has been started.}% } -% -% unknown self message label position error -\gdef\msc@unknowntimerposerr#1{% +% region already started error +\gdef\msc@regionstartederr#1#2{% \PackageError{msc}{% error message - unknown timer position: #1}{% help text - Known timer positions are "l" (left), "r" (right).\MessageBreak - You used '#1'.}% + region #2 is already started}{% help text + You tried to start new region for the instance "#1", \MessageBreak + while the previous region is still active.}% } -% % unknown self message label position error \gdef\msc@unknownmscvalueserr#1{% \PackageError{msc}{% error message @@ -3037,73 +3055,6 @@ 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{% @@ -3114,46 +3065,4 @@ 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 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 - +%reading /usr/share/texlive/texmf-dist/tex/latex/base/latex.ltx -- cgit v1.2.3