%%==================================================%% %%========Is based on the idea of framed.sty========%% %%==================================================%% %%===== Currently the package has a beta-Status ====%% %%==================================================%% %% WITH THANKS TO (alphabetically): %% ROLF NIEPRASCHK %% HEIKO OBERDIEK %% HERBERT VOSS %% Copyright (c) 2010 Marco Daniel % %% This package may be distributed under the terms of the LaTeX Project %% Public License, as described in lppl.txt in the base LaTeX distribution. %% Either version 1.0 or, at your option, any later version. %% %% %%==================================================%% %% Erstellung eines Rahmens, der am Seitenende keine %% horizontale Linie einfuegt %%>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>%% %% _______________ %% %% | page 1 | %% %% | Text | %% %% | __Text__ | %% %% | | Text | | %% %% P A G E B R E A K %% %% | | Text | | %% %% | |_Text_| | %% %% | Text | %% %% |____page 2___| %% %% %% %%>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>%% %%$Id: mdframed.sty 165 2011-08-30 09:55:55Z marco $ %%$Rev: 165 $ %%$Author: marco $ %%$Date: 2011-08-30 11:55:55 +0200 (Di, 30. Aug 2011) $ %% Allgemeine Angaben \def\mdversion{v0.8a} \def\mdframedpackagename{mdframed} \def\md@maindate@svn$#1: #2 #3 #4-#5-#6 #7 #8${#4/#5/#6\space } \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{mdframed}[\md@maindate@svn$Id: mdframed.sty 165 2011-08-30 09:55:55Z marco $ \mdversion: \mdframedpackagename] %%==================================================%% %%=============== Benoetigte Pakete ================%% %%==================================================%% \newcommand*\md@PackageWarning[1]{\PackageWarning{\mdframedpackagename}{#1}} \newcommand*\md@PackageInfo[1]{\PackageInfo{\mdframedpackagename}{#1}} \newcommand*\md@LoadFile@IfExist[1]{% \IfFileExists{#1.sty}{% \RequirePackage{#1}% }{% \md@PackageWarning{The package #1 does not exist\MessageBreak but it is required by \mdframedpackagename\MessageBreak see documentation fo further information }% } } \md@LoadFile@IfExist{kvoptions} \md@LoadFile@IfExist{etex} \md@LoadFile@IfExist{calc} \md@LoadFile@IfExist{color} \md@LoadFile@IfExist{etoolbox} \SetupKeyvalOptions{family=mdf,prefix=mdf@} %%==================================================%% %%============Hilfsmakros fuer Optionen=============%% %%==================================================%% %%%\md@iflength{}{}{} \newlength{\md@templength} \def\md@iflength#1{% \afterassignment\md@iflength@check% \md@templength=#1\mdf@defaultunit\relax\relax \expandafter\endgroup\next } \def\md@iflength@check#1{% \begingroup \ifx\relax#1\@empty \def\next{\@secondoftwo} \else \def\next{\@firstoftwo} \expandafter\md@iflength@cleanup \fi } \def\md@iflength@cleanup#1\relax{} %%\mdf@option@length{}{} \newrobustcmd*{\mdf@option@length}[2]{% \expandafter\newlength\csname mdf@#1@length\endcsname% \expandafter\setlength\csname mdf@#1@length\endcsname{#2}% } %%\mdf@define@key@length{} \newrobustcmd*{\mdf@define@key@length}[1]{% \define@key{mdf}{#1}{% \def\@tempa{##1} \md@iflength{\@tempa}% {\csxdef{mdfl@#1}{\the\md@templength}}% {\csxdef{mdfl@#1}{\the\md@templength}}% \expandafter\setlength\csname mdf@#1@length\endcsname{\csname mdfl@#1\endcsname}% }% } %%Schleifenmakro zur Optioneneingabe Option==Laenge \DeclareListParser*{\mdf@dolist}{,} \def\mdf@do#1{% \mdf@doubledo#1\@nil% } \def\mdf@doubledo#1==#2\@nil{% \mdf@option@length{#1}{#2}% \mdf@define@key@length{#1}% } %Festlegung welcher Stildatei %% 0 := tex-Kommandos -- rule %% 1 := tikz %% 2 := tikz-erweitert %% 3 := pstricks-einfach %% 4 := pstricks-erweitert \DeclareStringOption[0]{style} \define@key{mdf}{globalstyle}[\mdf@style]{% \def\md@styledo##1{% \def\@tempa{##1} \ifcase\number\@tempa\relax %0 <- kein Grafikpaket \or\md@LoadFile@IfExist{tikz}%1 <- tikz wird benoetigt \or\md@LoadFile@IfExist{tikz}%2 <- tikz wird benoetigt \or\md@LoadFile@IfExist{pstricks-add}%3 <- pstricks wird benoetigt \or\md@LoadFile@IfExist{pstricks-add}%4 <- pstricks wird benoetigt \else\md@PackageWarning{Unknown global style \@tempa}% \fi }% \mdf@dolist{\md@styledo}{\mdf@style,#1}% } %%%%Optionen mit Laengen \mdf@dolist{\mdf@do}{% {skipabove==\z@},% {skipbelow==\z@},% {leftmargin==\z@},% {rightmargin==\z@},% {margin==20pt},% {innerleftmargin==10pt},% {innerrightmargin==10pt},% {innertopmargin==0.4\baselineskip},% {innerbottommargin==0.4\baselineskip},% {splittopskip==\z@},% {splitbottomskip==\z@},% {outermargin==\z@},% {innermargin==\z@},% {linewidth==0.4pt},% {innerlinewidth==\z@},% {middlelinewidth==\expandafter\mdf@linewidth@length},% {outerlinewidth==\z@},% {roundcorner==\z@},% } %Unterstuetzung der Optionen fuer tikz \def\mdf@tikzset@local{\tikzset{tikzsetting/.style={}}} \define@key{mdf}{tikzsetting}{% \def\mdf@tikzset@local{\tikzset{tikzsetting/.style={#1}}} } %Unterstuetzung der Optionen fuer pstricks \def\mdf@psset@local{} \define@key{mdf}{pstrickssetting}{% \def\mdf@psset@local{#1} } \DeclareStringOption[pt]{defaultunit} %%mdframed umfasst ntheorem-Umgebung ja/nein \DeclareBoolOption{ntheorem} %Linienausgabe \DeclareBoolOption[true]{topline} \DeclareBoolOption[true]{leftline} \DeclareBoolOption[true]{bottomline} \DeclareBoolOption[true]{rightline} %%FARBEN \DeclareStringOption[none]{xcolor} \DeclareStringOption[black]{linecolor} \DeclareStringOption[white]{backgroundcolor} \DeclareStringOption[black]{fontcolor} \DeclareStringOption[\mdf@linecolor]{innerlinecolor} \DeclareStringOption[\mdf@linecolor]{outerlinecolor} \DeclareStringOption[\mdf@backgroundcolor]{middlelinecolor} \DeclareStringOption[\mdf@backgroundcolor]{psroundlinecolor} \DeclareDefaultOption{% \md@PackageWarning{Unknown Option '\CurrentOption' for mdframed}} %%Uberschriften \DeclareStringOption{frametitle} \DeclareStringOption[\bfseries\large]{frametitlefont} \ProcessKeyvalOptions* \newcommand*{\mdfsetup}{\setkeys{mdf}} \mdfsetup{globalstyle=0} %%==================================================%% %%========Sicherstellen der key-value-Syntax========%% %%==================================================%% \AtBeginDocument{ \@ifpackageloaded{xcolor}{% \let\mdf@xcolor\@empty %ignoriere die Eingabe der Optionen }{% \def\@tempa{none} \ifx\mdf@xcolor\@tempa \else \PassOptionsToPackage{\mdf@xcolor}{xcolor} \RequirePackage{xcolor} \fi } } %%==================================================%% %%========Angepasste lrbox sowie trivlist===========%% %%==================================================%% %Anpassung lrbox \let\md@lrbox\lrbox \let\endmd@lrbox\endlrbox \patchcmd\md@lrbox\hbox\vbox{}{} \patchcmd\md@lrbox\color@setgroup{% \color@setgroup\color{\mdf@fontcolor}% \hsize=\md@horizontalspaceofbox% \columnwidth=\hsize% \textwidth=\hsize% \linewidth=\hsize% \bgroup\md@@frametitle\egroup\noindent% }{}{} %Anpassung trivlist \let\md@trivlist\trivlist \let\endmd@trivlist\endtrivlist \patchcmd\endmd@trivlist\@endparenv\md@endparenv{}{} \def\md@endparenv{% \addpenalty\@endparpenalty\addvspace\mdf@skipbelow@length\@endpetrue} %%==================================================%% %%=============Umgebungdefinition===================%% %%==================================================%% %\newmdenv[]{} \newrobustcmd*\newmdenv[2][]{% \newenvironment{#2}{% \mdfsetup{#1}% \begin{mdframed}% }{% \end{mdframed}% }% } %\renewmdenv[]{} \newrobustcmd*\renewmdenv[2][]{% \expandafter\let\csname #2\endcsname\relax% \expandafter\let\csname end#2\endcsname\relax% \newmdenv[#1]{#2}% }% %http://tex.stackexchange.com/questions/26298/own-command-to-create-new-environment %\newtheorem{}[]{}[] %\newmdtheoremenv[]{}[]{}[] %\md@tempa[] %\md@tempb{}% %\md@tempc[]% %\md@tempd{}% %\md@tempe[]% \newrobustcmd*\newmdtheoremenv{% \kernel@ifnextchar[%] {\newmdtheoremenv@i}{\newmdtheoremenv@i[]}% } \def\newmdtheoremenv@i[#1]#2{% \def\md@tempa{#1}% \def\md@tempb{#2}% \kernel@ifnextchar[%] {\newmdtheoremenv@ii}{\newmdtheoremenv@ii[]}% } \def\newmdtheoremenv@ii[#1]#2{% \def\md@tempc{#1}% \def\md@tempd{#2}% \kernel@ifnextchar[%] {\newmdtheoremenv@iii}{\newmdtheoremenv@iii[]}% } \def\newmdtheoremenv@iii[#1]{% \def\md@tempe{#1}% \ifboolexpr{ not (test {\ifdefempty{\md@tempc}}) and not (test {\ifdefempty{\md@tempe}}) }{% \md@PackageWarning{You defined {\string\newtheorem} with ^^J both optional arguments^^J and . This isn't allowed^^J \mdframedpackagename will use \MessageBreak}% \newtheorem{\csname md\md@tempb \endcsname}[\md@tempc]{\md@tempd}% }% {\ifdefempty{\md@tempc}{}{\newtheorem{md\md@tempb}[\md@tempc]{\md@tempd}}% \ifdefempty{\md@tempe}{}{\newtheorem{md\md@tempb}{\md@tempd}[\md@tempe]}% }% \ifboolexpr{test {\ifdefempty{\md@tempc}} and test {\ifdefempty{\md@tempe}} }{% \newtheorem{md\md@tempb}{\md@tempd}% }{}% \expandafter\protected@xdef\csname\md@tempb\endcsname{\noexpand\mdfsetup{\md@tempa}% \noexpand\begin{mdframed}[]\noexpand\begin{md\md@tempb}% }% \expandafter\protected@xdef\csname end\md@tempb\endcsname{% \noexpand\end{md\md@tempb}\noexpand\end{mdframed}% }% } %%==================================================%% %%=================== Frametitle ===================%% %%==================================================%% \let\mdraggedtitle\raggedright \providecommand*\mdframedtitleenv[1]{% \@afterindentfalse {\parindent \z@ \setlength{\parfillskip}{\z@ plus 1fil}% \mdraggedtitle\nobreak\mdf@frametitlefont#1\relax% \par}% \@afterheading} % \newrobustcmd*\md@@frametitle{% \ifx\mdf@frametitle\@empty\relax% \else \color@begingroup\@nobreaktrue% \mdframedtitleenv{\mdf@frametitle}% \color@endgroup \fi% } \newrobustcmd*\md@checkntheorem{% \ifbool{mdf@ntheorem}% %%% Pruefen ob ntheorem gesetzt ist {\ifundef{\theorempreskipamount}% {\md@PackageWarning{You have not loaded ntheorem yet}}% {\setlength{\theorempreskipamount}{\z@}% \setlength{\theorempostskipamount}{\z@}% }% }{}% } %%==================================================%% %%======= Laden der gewuenschten Style-Datei =======%% %%==================================================%% \ifcase\mdf@style\relax% \input{md-frame-0.mdf}% \or\input{md-frame-1.mdf}% \or\md@PackageWarning{The style number\mdf@style does not exist\MessageBreak mdframed ues instead style=0 \mdframedpackagename}% \input{md-frame-0.mdf}% \or\input{md-frame-3.mdf}% \else% \IfFileExists{md-frame-\mdf@style.mdf}{\input{md-frame-\mdf@style.mdf}% }{\input{md-frame-1.mdf}% \md@PackageWarning{The style number \mdf@style does not exist\MessageBreak mdframed ues instead style=0 \mdframedpackagename}% }% \fi% %%==================================================%% %%========= style-abhaengige Modifikation ==========%% %%==================================================%% \newrobustcmd*\md@styledefinition{% \ifnumequal{\mdf@style}{0}% {\deflength{\mdf@innerlinewidth@length}{\z@}% \deflength{\mdf@middlelinewidth@length}{\mdf@linewidth@length}% \deflength{\mdf@outerlinewidth@length}{\z@}% \let\mdf@innerlinecolor\mdf@linecolor% \let\mdf@middlelinecolor\mdf@linecolor% \let\mdf@outerlinecolor\mdf@linecolor% }{}% \ifnumequal{\mdf@style}{3}% {\deflength{\mdf@innerlinewidth@length}{\z@}% \deflength{\mdf@middlelinewidth@length}{\mdf@linewidth@length}% \deflength{\mdf@outerlinewidth@length}{\z@}% \let\mdf@innerlinecolor\mdf@linecolor% }{}% % \ifnumequal{\mdf@style}{1}% % {\deflength{\mdf@innerlinewidth@length}{\z@}% % \deflength{\mdf@middlelinewidth@length}{\mdf@linewidth@length}% % \deflength{\mdf@outerlinewidth@length}{\z@}% % \let\mdf@innerlinecolor\mdf@linecolor% % }{}% } %%==================================================%% %%==Deklaration diverser Eingabe und Hilfsparameter=%% %%==================================================%% \newlength\mdfboundingboxheight \newlength\mdfboundingboxwidth \newlength\md@freevspace@length \newlength\md@horizontalwidthofbox@length \newlength\md@verticalmarginwhole@length \providecommand*\ptTps{} %%==================================================%% %%==================Umgebung========================%% %%==================================================%% \def\mdframed{\@ifnextchar[\mdframed@i\mdframed@ii}% \def\mdframed@ii{\mdframed@i[]}% \def\mdframed@i[#1]{% default-Umgebung \begingroup %check is needed? \mdfsetup{#1}%% \let\width\z@% \let\height\z@% \let\partopsep\z@ \setlength{\topsep}{\mdf@skipabove@length}% \begin{md@trivlist}\item\relax% \md@checkntheorem% \md@styledefinition% \md@horizontalmargin@equation% \begin{md@lrbox}{\@tempboxa}% }% \def\endmdframed{% \end{md@lrbox}% \md@put@frame% \end{md@trivlist}% \hrule \@height\z@ \@width\hsize \endgroup% } %%==================================================%% %%================= Platz auf Seite ================%% %%==================================================%% \newrobustcmd*\md@freepagevspace{% \penalty\@M \vskip 2\baselineskip \vskip\height \penalty9999 \vskip -2\baselineskip \vskip-\height \penalty9999 \ifdimequal{\pagegoal}{\maxdimen}% {\md@freevspace@length\vsize}% {\md@freevspace@length=\pagegoal\relax% \advance\md@freevspace@length by -\pagetotal\relax% }% } %%==================================================%% %================= Breite der Box =================%% %%==================================================%% \newrobustcmd*\md@advancelength@orizontalmargin@add[1]{% \advance\md@horizontalspaceofbox by -\csname mdf@#1@length\endcsname\relax% } \newlength\md@horizontalspaceofbox \newrobustcmd*\md@horizontalmargin@equation{% \setlength{\md@horizontalspaceofbox}{\hsize}% \mdf@dolist{\md@advancelength@orizontalmargin@add}{% leftmargin,outerlinewidth,middlelinewidth,% innerlinewidth,innerleftmargin,innerrightmargin,% innerlinewidth,middlelinewidth,outerlinewidth,% rightmargin}% \notbool{mdf@leftline}{% \advance\md@horizontalspaceofbox by \mdf@innerlinewidth@length\relax% \advance\md@horizontalspaceofbox by \mdf@middlelinewidth@length\relax% \advance\md@horizontalspaceofbox by \mdf@outerlinewidth@length\relax% }{}% \notbool{mdf@rightline}{% \advance\md@horizontalspaceofbox by \mdf@innerlinewidth@length\relax% \advance\md@horizontalspaceofbox by \mdf@middlelinewidth@length\relax% \advance\md@horizontalspaceofbox by \mdf@outerlinewidth@length\relax% }{}% % \advance\md@horizontalspaceofbox by - \width\md@arrayparboxrestore% %%% Beruecksichtigung, dass Auszaehlung bzw. list-Umgebung enthalten \ifdimless{\md@horizontalspaceofbox}{3cm}{\md@PackageWarning{You have only a width of 3cm}}{} \hsize=\md@horizontalspaceofbox% } %%==================================================%% %%===========Beruecksichtige Linienausgabe==========%% %%==================================================%% \newrobustcmd*\md@keeplines@single{% \notbool{mdf@topline}{% \advance\md@verticalmarginwhole@length by -\mdf@middlelinewidth@length% }{}% \notbool{mdf@bottomline}{% \advance\md@verticalmarginwhole@length by -\mdf@middlelinewidth@length% }{}% } %%==================================================%% %%===========Additionsalgorithmus fuer for==========%% %%==================================================%% \newrobustcmd*\md@advancelength@verticalmarginwhole[1]{% \advance\md@verticalmarginwhole@length by \csname mdf@#1@length\endcsname\relax% } \newrobustcmd*\md@advancelength@freevspace@sub[1]{% \advance\dimen@ by -\csname mdf@#1@length\endcsname\relax% } \newrobustcmd*\md@advancelength@freevspace@add[1]{% \advance\dimen@ by \csname mdf@#1@length\endcsname\relax% } %%==================================================%% %%====================Reset changes=================%% %%==================================================%% \protected@edef\md@reset{\boxmaxdepth\the\boxmaxdepth \splittopskip\the\splittopskip}% %%==================================================%% %%===========Ausgaberoutine -> Berechnung===========%% %%==================================================%% \def\md@put@frame{\relax% \ifvoid\@tempboxa\relax \md@PackageWarning{The environment is empty\MessageBreak}% \else \md@freepagevspace% \ifdimless{\md@freevspace@length}{2\baselineskip} {\md@PackageInfo{Not enough space on this page}%die Seite hat nur noch minimal Platz \vfill\eject% \md@put@frame }{% %Hier berechnung Box-Inhalt+Rahmen oben und unten \setlength{\md@verticalmarginwhole@length}{\ht\@tempboxa+\dp\@tempboxa}% \mdf@dolist{\md@advancelength@verticalmarginwhole}{% outerlinewidth,middlelinewidth,innerlinewidth,innertopmargin, innerbottommargin,innerlinewidth,middlelinewidth,outerlinewidth}% \md@keeplines@single% \ifdimless{\md@verticalmarginwhole@length}{\md@freevspace@length}% {\md@putbox@single}%passt auf Seite {\md@put@frame@i}%passt nicht auf Seite }% \fi } \def\md@put@frame@i{%Box muss gesplittet werden -- Ausgabe der ersten Teilbox %Berechnung der Splittgroesse -- Linien und Abstand oben \md@freepagevspace% \dimen@=\the\md@freevspace@length% \dimen@i=\mdf@innertopmargin@length% \advance\dimen@i by \mdf@linewidth@length% \advance\dimen@i by 2\baselineskip% \ifdim\dimen@<\dimen@i\relax \hrule \@height\z@ \@width\hsize% \vfill\eject% \md@put@frame \else% \mdf@dolist{\md@advancelength@freevspace@sub}{% outerlinewidth,middlelinewidth,innerlinewidth,% innertopmargin,splitbottomskip}% \ifbool{mdf@topline}{}{\advance\dimen@ by \mdf@middlelinewidth@length}% \ifdimless{\ht\@tempboxa+\dp\@tempboxa}{\dimen@}% {\md@PackageWarning{You got a bad break\MessageBreak you have to change it manually\MessageBreak by changing the text, the space\MessageBreak or something else}% \advance\dimen@ by -1.8\baselineskip\relax% }{}% \advance\dimen@ by -1pt\relax%Box darf nicht zu Groß werden. \splitmaxdepth\z@ \splittopskip\mdf@splittopskip@length% \setbox\tw@\vsplit\@tempboxa to \dimen@ \setbox\tw@\vbox{\unvbox\tw@}%needed? \ifdimgreater{\ht\tw@+\dp\tw@}{\dimen@}{%Falsch gesplittet \md@PackageInfo{Box was splittet wrong\MessageBreak}% \dimen@i=\dimen@ \advance\dimen@ by -\ht\tw@ \advance\dimen@ by -\dp\tw@ \advance\dimen@i by 0.5\dimen@ \splittopskip\z@% \setbox\@tempboxa\vbox{\unvbox\tw@% \hrule \@height\dp\strutbox \@width\z@%benoetigt um Tiefe zu haben \unvbox\@tempboxa} \splittopskip\mdf@splittopskip@length% \setbox\tw@\vsplit\@tempboxa to \dimen@i \setbox\tw@\vbox{\unvbox\tw@}% }{}% \setbox\@tempboxa\vbox{\unvbox\@tempboxa}%PRUEFEN!!!! \ifvoid\@tempboxa \md@PackageWarning{You got a bad break\MessageBreak because the splittet box is empty\MessageBreak You have to change the page settings\MessageBreak like enlargethispage or something else}% \setbox\@tempboxa\vbox{\box\tw@\box\@tempboxa}% \md@put@frame \fi \ifvoid\tw@%%pruefe, ob erste Box leer ist \hrule \@height\z@ \@width\hsize \vfill\eject% \md@put@frame% \else \ifdimequal{\ht\tw@}{0pt} {\hrule \@height\z@ \@width\hsize% \vfill\eject% \setbox\@tempboxa\vbox{\unvbox\tw@\unvbox\@tempboxa} \md@put@frame}% {% \md@putbox@first%%Groesse des Splittens passt \hrule \@height\z@ \@width\hsize \vfill\eject% \md@put@frame@ii% } \fi% \fi } \def\md@put@frame@ii{%Ausgabe der mittleren Box(en) wenn vorhanden \setlength{\md@freevspace@length}{\vsize}% \setlength{\dimen@}{\ht\@tempboxa+\dp\@tempboxa}% \mdf@dolist{\md@advancelength@freevspace@add}{% outerlinewidth,middlelinewidth,innerlinewidth,% innerbottommargin}%%%Addition der Linien unten \ifbool{mdf@bottomline}{}{\advance\dimen@ by -\mdf@middlelinewidth@length\relax}% \ifdimgreater{\dimen@}{\md@freevspace@length}% {% \advance\md@freevspace@length by -\mdf@splitbottomskip@length \splitmaxdepth\z@ \splittopskip\mdf@splittopskip@length% \setbox\tw@\vsplit\@tempboxa to \md@freevspace@length% \setbox\tw@\vbox{\unvbox\tw@}%PRUEFEN!!! \setbox\@tempboxa\vbox{\unvbox\@tempboxa}%PRUEFEN!!!! \ifvoid\@tempboxa\relax% \md@PackageWarning{You got a bad break\MessageBreak because the splittet box is empty\MessageBreak You have to change the settings}% \fi% \md@putbox@middle% \hrule \@height\z@ \@width\hsize \vfill\eject \md@put@frame@ii% }%Hier die Ausgabe der mittleren Box {\ifvoid\@tempboxa \md@PackageWarning{You got a bad break\MessageBreak because the last splittet box is empty\MessageBreak You have to change the settings}% \fi% \md@putbox@second% }%Hier kommt die Ausgabe der letzten Box } %%==================================================%% %%= Sicherstellen, dass Optionen nur global setzbar=%% %%==================================================%% \DisableKeyvalOption[% action=warning, package=mdframed, ]{mdf}{globalstyle}% \DisableKeyvalOption[% action=warning, package=mdframed, ]{mdf}{xcolor}% \endinput %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%