%% MSC Macro Package %% msc.sty %% %% 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 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is P. Kordy % % This program consists of the files % msc.sty % manual.tex % manual_macros.tex % biblio.bib % README % COPYRIGHT % Contact address: % 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{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, } % 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}% } \newcommand{\mscgety}[2]{% \tikz@scan@one@point\pgfutil@firstofone#1\relax \edef#2{\the\pgf@y}% } % 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 } % % * Shapes * % % %% A rectangle with right side open % \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 } } % \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 } %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} } } % #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 } } %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} } } %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} } } } % \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@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} } }{ \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@dist{-\mscget{msccomment distance}} } { \def\msc@anchor{west} \edef\msc@dist{\mscget{msccomment distance}} } \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} } } % \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} } } \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} } } % \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} } } %\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} } } % \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}; } \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}; } \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} } } %\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} }{} } % \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 % instance of the condition % - The last instance nickname is supposed to be the rightmost % instance of the condition % \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} } } % \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)}); } } % 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)}); } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CO-REGIONS % % \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}}% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % REGIONS (normal, coregion, suspension, and activation) % % % 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); } }{ \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); } } }{ \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); } }{ \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); } } } % \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 } % 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 } % 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} } } %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} } } } } \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} } }{ \end{pgfscope}\msc@instundefinederr{#3} } } \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 } } \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} } }{ \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[]} } } } \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}} } \def\mscunit{cm}% \def\msckeywordstyle#1{\textbf{#1}} \newcommand{\setmsckeyword}[1]{\mscset{/msc/msc keyword={#1}}} \newcommand{\setmsckeywordstyle}[1]{\def\msckeywordstyle{#1}}% \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}}% %\mscset but globally \def\msc@global@set#1{\globaldefs=1\relax\mscset{#1}\globaldefs=0\relax}% % the msc-environment % \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{}% }% {\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={}} }{} } % \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 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \def\msckeywordstyle#1{\textbf{#1}} \newcommand{\sethmsckeyword}[1]{\mscset{/msc/hmsc keyword={#1}}}% \newcommand{\sethmsckeywordstyle}[1]{\def\hmsckeywordstyle{#1}}% % \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 \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 } } \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 } } \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 } %\hmscendsymbol{nickname}(x,y) \def\hmscendsymbol{ \edef\msc@nodetype{end symbol} \pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]} } %\hmscreference{nickname}{text}(x,y) \def\hmscreference{ \edef\msc@nodetype{reference} \pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]} } %\hmsc condition{nickname}{text}(x,y) \def\hmsccondition{ \edef\msc@nodetype{condition} \pgfutil@ifnextchar[\msc@nodetext{\msc@nodetext[]} } %\hmscconnection{nickname}(x,y) \def\hmscconnection{ \edef\msc@nodetype{connection} \pgfutil@ifnextchar[\msc@nodenotext{\msc@nodenotext[]} } %\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} } \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 } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % MSC documents % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \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 } } \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 } \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}} } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Error and help messages % We use the standard LaTeX2e facilities to generate error and help % messages (for more info, see file lterror.dtx of LaTeX2e distribution). % % % nickname already defined \gdef\msc@nicknamedefinederr#1{% \PackageError{msc}{% error message nickname #1 already defined}{% help text You tried to use the nickname '#1' for a new\MessageBreak msc object (instance, reference, inline expression, etc.),\MessageBreak but the nickname is already assigned to another msc object.\MessageBreak press 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 undefined msc instance: #1}{% help text You used '#1' as an msc instance nickname, but\MessageBreak there is no msc instance with that nickname.}% } % 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 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 "coregion", "suspension", and "activation".\MessageBreak You used '#1'.}% } % region not started error \gdef\msc@regionnotstartederr#1{% \PackageError{msc}{% error message 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.}% } % region already started error \gdef\msc@regionstartederr#1#2{% \PackageError{msc}{% error message 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 unknown set of msc-values: #1}{% help text Known sets of msc-values are "normal" and "small".\MessageBreak You used '#1'.}% } %################################################################################ % \gdef\msc@illegaltitleplacement#1{% \PackageError{msc}{% illegal title placement specifier: #1}{% help text Valid title placement specifiers are:\MessageBreak l (left)\MessageBreak c (center)\MessageBreak r (right)} } %reading /usr/share/texlive/texmf-dist/tex/latex/base/latex.ltx