From fca241c91ba0f27d145bf083a283491844da1da1 Mon Sep 17 00:00:00 2001 From: "Richard L. Ford" Date: Wed, 27 Jan 2016 21:35:30 -0800 Subject: Add Dafny reference manual This version is still a draft, but is mostly complete and about half reviewed. The manual is written using Madoko. The sources are in the Docs/DafnyRef directory. The processed sources are available in the Docs/DafnyRef/out directory in the form of a single HTML page or as a PDF. --- Docs/DafnyRef/css.sty | 803 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 803 insertions(+) create mode 100644 Docs/DafnyRef/css.sty (limited to 'Docs/DafnyRef/css.sty') diff --git a/Docs/DafnyRef/css.sty b/Docs/DafnyRef/css.sty new file mode 100644 index 00000000..aab82e69 --- /dev/null +++ b/Docs/DafnyRef/css.sty @@ -0,0 +1,803 @@ +%--------------------------------------------------------------------------- +% Copyright 2013 Microsoft Corporation. +% +% This is free software; you can redistribute it and/or modify it under the +% terms of the Apache License, Version 2.0. A copy of the License can be +% found in the file "license.txt" at the root of this distribution. +%--------------------------------------------------------------------------- +\NeedsTeXFormat{LaTeX2e}[1995/12/01] + +\RequirePackage{iftex} +\RequirePackage{etoolbox} +\RequirePackage{xkeyval} +\RequirePackage[table]{xcolor} +\RequirePackage{mdframed} +\RequirePackage{graphicx} +\RequirePackage{tablefootnote} + +% font selection +\ifXeTeX\RequirePackage{fontspec}\else +\ifLuaTeX\RequirePackage{fontspec}\else +\providecommand{\fontspec}[2][]{} +\fi\fi + + +% Define CSS 17 standard colors +\definecolor{Red}{HTML}{FF0000} +\definecolor{Lime}{HTML}{00FF00} +\definecolor{Blue}{HTML}{0000FF} + +\definecolor{Yellow}{HTML}{FFFF00} +\definecolor{Cyan}{HTML}{00FFFF} +\definecolor{Magenta}{HTML}{FF00FF} + +\definecolor{Navy}{HTML}{000080} +\definecolor{Maroon}{HTML}{800000} +\definecolor{Green}{HTML}{008000} + +\definecolor{Teal}{HTML}{008080} +\definecolor{Purple}{HTML}{800080} +\definecolor{Olive}{HTML}{808000} + +\definecolor{Black}{HTML}{000000} +\definecolor{Dimgray}{HTML}{696969} +\definecolor{Gray}{HTML}{808080} +\definecolor{Darkgray}{HTML}{A9A9A9} +\definecolor{Silver}{HTML}{C0C0C0} +\definecolor{Lightgray}{HTML}{D3D3D3} +\definecolor{Gainsboro}{HTML}{DCDCDC} +\definecolor{Floralwhite}{HTML}{FFFAF0} +\definecolor{Ivory}{HTML}{FFFFF0} +\definecolor{White}{HTML}{FFFFFF} + +\definecolor{Orange}{HTML}{FFA500} +\definecolor{Aqua}{HTML}{00FFFF} +\definecolor{Fuchsia}{HTML}{FF00FF} + +\newcommand{\@swap}[2]{#2{#1}} +\newcommand{\@expandafter}[2]{\expandafter\@swap\expandafter{#2}{#1}} + +\newcommand{\eifstrequal}{\expandafter\ifstrequal\expandafter} +\newcommand{\eeifstrequal}[2]{\@expandafter{\eifstrequal{#1}}{#2}} + +\providecommand\providelength[1]{% + \begingroup + \escapechar\m@ne + \xdef\@gtempa{\string#1}% + \endgroup + \@ifundefined{\@gtempa}% + {\newskip#1}% + {}% +} + +% is a string an element of a list of (comma separated) strings +\newcommand{\eifstrelement}[4]{% + \def\@found{}% + \@for\@ii:=#2\do{% + \eeifstrequal{\@ii}{#1}{\def\@found{true}}{}% + }% + \ifdefvoid{\@found}{#4}{#3}% +} + +% do two lists of strings intersect? +\newcommand{\ifintersect}[4]{% + \def\@intersect{}% + \@for\@sname:=#1\do{% + \ifdefvoid{\@intersect}{% + \eifstrelement{\@sname}{#2}{\def\@intersect{true}}{}% + }{}% + }% + \ifdefvoid{\@intersect}{#4}{#3}% +} + +% get string head and tail +\def\strsplit#1{\expandafter\strsplitx#1\empty\empty\empty} +\def\strsplitx#1#2\empty{% + \edef\strhead{#1}% + \edef\strtail{#2}% +} + +% normalize colors: to lowercase and then capitalize +\newcommand{\cssDefNormalizeColor}[2]{% + \expandafter\@cssNormColor#2\empty{#1}\empty% +} +\def\@cssNormColor#1#2\empty#3\empty{% + \uppercase{\def\@hd{#1}}\lowercase{\def\@tl{#2}}% + \expandafter\global\expandafter\edef\csname #3\endcsname{\@hd\@tl}% +} + + +% --------------------------------------------------- +% Some TeX stuff to compose functions +% --------------------------------------------------- +\newcommand{\apptox}[2]{% apptox{\cmd1}{\cmd2} == newcommand{\cmd1'}[1]{\cmd1{\cmd2{#1}}} + \providecommand{#1}[1]{##1}% define it if necessary (as identity) + \protected@edef#1##1{#1{\protect #2{##1}}}% +} + +\newcommand{\pretox}[2]{% pretox{\cmd1}{\cmd2} == newcommand{\cmd1'}[1]{\cmd2{\cmd1{#1}}} + \providecommand{#1}[1]{##1}% + \protected@edef#1##1{\protect #2{#1{##1}}}% +} + +%------------------------------------------------------------- +% Save footnotes inside mdframed and minipage environments +%------------------------------------------------------------- +\newif\if@saveFootnotes +\newcommand{\cssSaveFootnotes}% + {\if@saveFootnotes\else% + \let\footnote\tablefootnote% + \fi% + \@saveFootnotestrue}% +\newcommand{\cssRestoreFootnotes}% + {\if@saveFootnotes\else% + \tfn@tablefootnoteprintout% + \gdef\tfn@fnt{0}% + \fi}% + +%------------------------------------------------------------- +% Setup mdframed with default values +%------------------------------------------------------------- +\newlength{\cssPixel}\setlength{\cssPixel}{0.4pt}% assume 180 dpi +\mdfsetup{% + leftmargin=0pt,% + rightmargin=0pt,% + skipabove=0pt,% + skipbelow=0pt,% + innertopmargin=0pt,% + innerbottommargin=0pt,% + innerleftmargin=0pt,% + innerrightmargin=0pt,% + middlelinewidth=0pt,% + linewidth=0pt,% + outerlinewidth=0pt,innerlinewidth=0pt% +} + + +% --------------------------------------------------- +% Basic command to process attributes passed to TeX +% --------------------------------------------------- +\newif\if@usewrap +\newcommand{\@doBefore}{} +\newcommand{\@doAfter}{} +\newcommand{\@wrapCmd}[1]{#1} + +\newcommand{\@cssUseCmd}{\renewcommand{\@wrapCmd}[1]{##1}\@usewraptrue} +\newcommand{\@cssUseEnv}{\renewcommand{\@doBefore}{}\renewcommand{\@doAfter}{}\@usewrapfalse} + +\newcommand{\@cssApplyCmd}[1]{{\@wrapCmd{#1}}} +\newcommand{\@cssApplyBefore}{\@doBefore{}} +\newcommand{\@cssApplyAfter}{\@doAfter{}} + +\newcommand{\@cssProcessAttrs}[2]{% + \setkeys*{cssx}{#1}\setrmkeys*{csspre}\setrmkeys*{css}\setrmkeys*{csspost}% defaults + \@cssApplyRulesFor{parentclass}{css}{\cssParentClass}% + \setkeys*{cssx}{#2}\setrmkeys*{csspre}\setrmkeys*{css}\setrmkeys*{csspost}% regular + \protected@edef\cssParentClass{\cssClass}% +} + + +\newcommand{\@cmdBefore}[2]{#1#2} +\newcommand{\@cmdAfter}[2]{#2#1} + +\newcommand{\cssWrapCmd}[1]{\apptox{\@wrapCmd}{#1}} +\newcommand{\cssDoBefore}[1]{\if@usewrap\cssWrapCmd{\@cmdBefore{#1}}\else #1\fi} +\newcommand{\cssDoAfter}[1]{\if@usewrap\cssWrapCmd{\@cmdAfter{#1}}\else\preto\@doAfter{#1}\fi} + +\newcommand{\cssDoEnv}[1]{\cssDoBefore{\protect\begin{#1}}\cssDoAfter{\protect\end{#1}}} +\newcommand{\cssDoEnvOpt}[2]{\cssDoBefore{\begin{#1}[#2]}\cssDoAfter{\end{#1}}} +\newcommand{\cssDoEnvArg}[2]{\cssDoBefore{\begin{#1}{#2}}\cssDoAfter{\end{#1}}} +\newcommand{\cssDoEnvArgII}[3]{\cssDoBefore{\begin{#1}{#2}{#3}}\cssDoAfter{\end{#1}}} + +\newcommand{\newKey}[4][]{\define@key{#2}{#3}[#1]{#4}} +\newcommand{\newLength}[2]{\providelength{#1}\setlength{#1}{#2}} + + +\newcommand{\@cssReset}{} +\newcommand{\cssAddReset}[1]{\appto{\@cssReset}{#1}} +\newcommand{\cssNewResetCommand}[2]{\newcommand{#1}{#2}\cssAddReset{\renewcommand{#1}{#2}}} + +\newlength{\cssFill} +\setlength{\cssFill}{2sp plus 1fill minus 2sp} % make \fill unequal to 0pt, and detectable as 2sp + +\newcommand{\cssNewLengthKey}[4][0pt]{% + \newLength{#4}{#1}% + \newKey{#2}{#3}{% + \ifstrequal{##1}{auto}{\setlength{#4}{\cssFill}}{\setlength{#4}{##1}}% + }% + \cssAddReset{\setlength{#4}{#1}}% +} + + +\newcommand{\cssNewKeyNoReset}[4]{% + \newcommand{#3}{#4}% + \newKey{#1}{#2}{\renewcommand{#3}{##1}}% +} + +\newcommand{\cssNewKey}[4]{% + \cssNewResetCommand{#3}{#4}% + \newKey{#1}{#2}{%(#2=##1)%debug key setting + \renewcommand{#3}{##1}}% +} +\newcommand{\cssNewKeyX}[5]{% + \cssNewResetCommand{#3}{#4}% + \newKey{#1}{#2}{\renewcommand{#3}{##1}#5{##1}}% +} +\newcommand{\cssNewListKey}[4]{% + \cssNewResetCommand{#3}{#4}% + \newKey{#1}{#2}{\appto{#3}{,##1}}% +} +\newcommand{\cssNewListKeyX}[5]{% + \cssNewResetCommand{#3}{#4}% + \newKey{#1}{#2}{\appto{#3}{,##1}#5{##1}}% +} +\newcommand{\cssNewPseudoKey}[3]{% + \newKey{#1}{#2}{\setkeys{#1}{#3}}% +} + +%------------------------------------------------------------- +% css: display +%------------------------------------------------------------- +\cssNewKey{css}{display}{\cssDisplay}{block} + +%------------------------------------------------------------- +% css: width, height, and margins +%------------------------------------------------------------- + +\cssNewLengthKey{css}{margin-left}{\cssMarginLeft} +\cssNewLengthKey{css}{margin-right}{\cssMarginRight} +\cssNewLengthKey{css}{margin-top}{\cssMarginTop} +\cssNewLengthKey{css}{margin-bottom}{\cssMarginBottom} +\cssNewLengthKey[1sp]{css}{width}{\cssWidth} +\cssNewLengthKey[1sp]{css}{height}{\cssHeight} +\cssNewKey{css}{vertical-align}{\cssVerticalAlign}{} + +\cssNewPseudoKey{css}{margin}{margin-top=#1,margin-bottom=#1,margin-left=#1,margin-right=#1} + + +\newcommand{\@cssProcessMargins}{% + \eifstrequal{\cssDisplay}{block}% + {\@cssBlockEndPar\@cssBlockMargins}% + {\eifstrequal{\cssDisplay}{block-inline}% + {\@cssBlockMargins}% + {\@cssInlineMargins}% + }% +} + +\newcommand{\@cssBlockEndPar}{% + \cssIfHasClass{para-continue,para-block}{}{\cssDoAfter{\relax\ifhmode\par\global\hangindent=0pt\fi}}% +} + +\newif\if@hasdim + +\newlength{\cssHeightFull} % height including padding and border +\newlength{\cssWidthFull} % width including padding and border +\newLength{\@cssMarginAfter}{0pt} +\newLength{\@cssParSkip}{\parskip} +\newLength{\@cssParIndent}{\parindent} +\newcommand{\@cssFixMathSpacing}{\strut\vspace{-\baselineskip}} % fixes weird abovedisplay skip spacing +\newcommand{\@cssBlockMargins}{% + \@hasdimfalse + \ifdim\cssWidth=1sp\setlength{\cssWidthFull}{1sp}\else\@hasdimtrue\fi + \ifdim\cssHeight=1sp\setlength{\cssHeightFull}{1sp}\else\@hasdimtrue\fi + \if@hasdim% + % set full height and width + \setlength{\cssWidthFull}{\dimexpr\cssWidth+\cssPaddingLeft+\cssPaddingRight\relax}% + \eifstrequal{\cssBorderLeftStyle}{none}{}{\addtolength{\cssWidthFull}{\cssBorderWidth}}% + \eifstrequal{\cssBorderRightStyle}{none}{}{\addtolength{\cssWidthFull}{\cssBorderWidth}}% + \setlength{\cssHeightFull}{\dimexpr\cssHeight+\cssPaddingTop+\cssPaddingBottom\relax}% + \eifstrequal{\cssBorderTopStyle}{none}{}{\addtolength{\cssHeightFull}{\cssBorderWidth}}% + \eifstrequal{\cssBorderBottomStyle}{none}{}{\addtolength{\cssHeightFull}{\cssBorderWidth}}% + % set default width? + \ifdim\cssWidth=1sp% in this case, cssWidthFull is just padding and borders + \setlength{\cssWidth}{\dimexpr\linewidth-\cssWidthFull-\cssMarginLeft-\cssMarginRight}% + \addtolength{\cssWidthFull}{\cssWidth}% + \fi% + %minipage + \ifdim\cssMarginTop=0pt\else\cssDoBefore{\vspace{\cssMarginTop}}\fi + \ifdim\cssMarginLeft=0pt\else\cssDoBefore{\hspace*{\cssMarginLeft}}\fi + \setlength{\@cssParIndent}{\parindent}% save parskip and parindent since minipage resets it + \setlength{\@cssParSkip}{\parskip}% + \eifstrequal{\cssVerticalAlign}{bottom}{\def\@cssValign{b}}% + {\eifstrequal{\cssVerticalAlign}{center}{\def\@cssValign{c}}% + {\eifstrequal{\cssVerticalAlign}{top}{\def\@cssValign{t}}% + {\def\@cssValign{c}}}}% including `middle` + \ifdim\cssHeight=1sp% + \cssDoBefore{\begin{minipage}[\@cssValign]{\cssWidthFull}}% + \else + \cssDoBefore{\begin{minipage}[\@cssValign][\cssHeightFull]{\cssWidthFull}}% + \fi + \cssDoBefore{\cssSaveFootnotes\setlength{\parskip}{\@cssParSkip}\setlength{\parindent}{\@cssParIndent}}% + %note: DoAfter prepends, so in opposite order + \ifdim\cssMarginBottom=0pt\else\cssDoAfter{\vspace{\cssMarginBottom}}\fi + \ifdim\cssMarginRight=0pt\else\cssDoAfter{\hspace*{\cssMarginRight}}\fi + \cssDoAfter{\end{minipage}\cssRestoreFootnotes}% + \else + % no height/width: trivlist + \@hasdimfalse + \ifdim\cssMarginLeft=0pt\else\@hasdimtrue\fi + \ifdim\cssMarginRight=0pt\else\@hasdimtrue\fi + \ifdim\cssMarginTop=0pt\else\@hasdimtrue\fi + \ifdim\cssMarginBottom=0pt\else\@hasdimtrue\fi + \if@hasdim + \setlength{\@cssMarginAfter}{\dimexpr\cssMarginBottom-\cssMarginTop\relax}% + \cssDoEnvArgII{list}{}{% + \leftmargin=\cssMarginLeft% + \rightmargin=\cssMarginRight% + \topsep=\cssMarginTop% + \itemsep=0pt% + \parsep=0pt% + \parskip=0pt% + \partopsep=0pt% + \listparindent=\parindent% + }% + \ifdim\@cssMarginAfter=0pt\else\cssDoAfter{\vspace{\@cssMarginAfter}}\fi% + \cssIfHasClass{math-display}% + {\cssDoBefore{\item\@cssFixMathSpacing}}% + {\cssDoBefore{\item}}% \fi + \fi + \fi +} + +\newcommand{\@cssHide}[1]{} +\newcommand{\@cssInlineMargins}{% + \ifdim\cssMarginLeft=0pt\else\cssDoBefore{\hspace*{\cssMarginLeft}}\fi + \ifdim\cssMarginRight=0pt\else\cssDoAfter{\hspace*{\cssMarginRight}}\fi + \ifdim\cssMarginBottom=0pt\else\cssDoBefore{\rule[-\cssMarginBottom]{0pt}{\cssMarginBottom}}\fi + \ifdim\cssMarginTop=0pt\else\cssDoBefore{\rule{0pt}{\dimexpr\baselineskip*0.7+\cssMarginTop\relax}}\fi + \eifstrequal{\cssDisplay}{hidden}{% + \cssWrapCmd{\@cssHide}% + }{}% +} + +%------------------------------------------------------------- +% css: Borders and padding +%------------------------------------------------------------- + +\cssNewLengthKey{css}{padding-left}{\cssPaddingLeft} +\cssNewLengthKey{css}{padding-right}{\cssPaddingRight} +\cssNewLengthKey{css}{padding-top}{\cssPaddingTop} +\cssNewLengthKey{css}{padding-bottom}{\cssPaddingBottom} + +\newlength{\cssBorderWidthTotal} +\cssNewLengthKey[\cssPixel]{css}{border-width}{\cssBorderWidth} +\cssNewKey{css}{border-color}{\cssBorderColor}{black} +\cssNewKey{css}{border-top-style}{\cssBorderTopStyle}{none} +\cssNewKey{css}{border-bottom-style}{\cssBorderBottomStyle}{none} +\cssNewKey{css}{border-left-style}{\cssBorderLeftStyle}{none} +\cssNewKey{css}{border-right-style}{\cssBorderRightStyle}{none} +\cssNewKey{css}{background-color}{\cssBackgroundColor}{white} + +\cssNewPseudoKey{css}{padding}{padding-top=#1,padding-bottom=#1,padding-right=#1,padding-left=#1} + +\cssNewPseudoKey{css}{border-style}% + {border-top-style=#1,border-bottom-style=#1,border-left-style=#1,border-right-style=#1} + +\newcommand{\@cssProcessPadding}{% + \eifstrequal{\cssDisplay}{block}% + {\@cssBlockPadding}% + {\eifstrequal{\cssDisplay}{block-inline}% + {\@cssBlockPadding}% + {\@cssInlinePadding}% + }} + +% Special math-framed environment that fixes vertical spacing around math display +\newenvironment{mdmathframed}[1][]% + {\begin{mdframed}[#1]\@cssFixMathSpacing}% + {\@cssFixMathSpacing\end{mdframed}} + + +\newif\if@needframe +\newLength{\@cssPaddingLength}{0pt} +\newcommand{\@cssFramedArgs}{} +\newcommand{\@cssBorderStyleAll}{} +\newcommand{\@cssBlockPadding}{% + \@needframefalse% + \eifstrequal{\cssBorderTopStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderBottomStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderLeftStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderRightStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBackgroundColor}{white}{}{\@needframetrue}% + \ifdim\cssPaddingTop=0pt\else\@needframetrue\fi + \ifdim\cssPaddingBottom=0pt\else\@needframetrue\fi + \ifdim\cssPaddingLeft=0pt\else\@needframetrue\fi + \ifdim\cssPaddingRight=0pt\else\@needframetrue\fi + \strsplit{\cssBackgroundColor}% + \eifstrequal{\strhead}{\#}% + {\definecolor{Temp}{HTML}{\strtail}\edef\@@bcolor{Temp}}% + {\cssDefNormalizeColor{@bcolor}{\cssBackgroundColor}\edef\@@bcolor{\@bcolor}}% + %\expandafter\lowercase\expandafter{\expandafter\def\expandafter\bcolor\expandafter{\cssBackgroundColor}}% + \if@needframe% + \cssDoAfter{\cssRestoreFootnotes}% first, because post commands are pre-pended + \renewcommand{\@cssFramedArgs}{% + innertopmargin=\the\cssPaddingTop,% + innerbottommargin=\the\cssPaddingBottom,% + innerleftmargin=\the\cssPaddingLeft,% + innerrightmargin=\the\cssPaddingRight,% + linewidth=\the\cssBorderWidth,% + linecolor=\cssBorderColor,% + backgroundcolor=\@@bcolor% + }% + \setlength{\cssBorderWidthTotal}{0pt}% + \eifstrequal{\cssBorderTopStyle}{none}{\appto{\@cssFramedArgs}{,topline=false}}{}% + \eifstrequal{\cssBorderBottomStyle}{none}{\appto{\@cssFramedArgs}{,bottomline=false}}{}% + \eifstrequal{\cssBorderLeftStyle}{none}{\appto{\@cssFramedArgs}{,leftline=false}}% + {\addtolength{\cssBorderWidthTotal}{\cssBorderWidth}}% + \eifstrequal{\cssBorderRightStyle}{none}{\appto{\@cssFramedArgs}{,rightline=false}}% + {\addtolength{\cssBorderWidthTotal}{\cssBorderWidth}}% + \cssIfHasClass{math-display}% + {\@expandafter{\cssDoEnvOpt{mdmathframed}}{\@cssFramedArgs}}% + {\@expandafter{\cssDoEnvOpt{mdframed}}{\@cssFramedArgs}}% + % insert a minipage if height or width was set so the frame is as large + \@hasdimfalse + \ifdim\cssWidth=1sp\else\@hasdimtrue\fi + \ifdim\cssHeight=1sp\else\@hasdimtrue\fi + \if@hasdim% + \ifdim\cssHeight=1sp% + \cssDoBefore{\begin{minipage}{\cssWidth}}% + \else + \cssDoBefore{\begin{minipage}[t][\cssHeight]{\cssWidth}}% + \fi + \cssDoBefore{\setlength{\parskip}{\@cssParSkip}\setlength{\parindent}{\@cssParIndent}}% + %note: DoAfter prepends, so in opposite order + \cssDoAfter{\end{minipage}}% + \fi + \cssDoBefore{\cssSaveFootnotes}% + \fi +} + +\newcommand{\@robustFramebox}[2]{% + \eifstrequal{\cssTextAlign}{center}{\framebox[#1][c]{#2}}% + {\eifstrequal{\cssTextAlign}{right}{\framebox[#1][r]{#2}}% + {\framebox[#1][l]{#2}}}% +} + +\newcommand{\@robustMakebox}[2]{% + \eifstrequal{\cssDisplay}{table-cell}% + {\@robustTableParbox{#1}{#2}}% + {\eifstrequal{\cssTextAlign}{center}{\makebox[#1][c]{#2}}% + {\eifstrequal{\cssTextAlign}{right}{\makebox[#1][r]{#2}}% + {\makebox[#1][l]{#2}}}}% +} + +\newcommand{\@robustRaisebox}[2]{% + \raisebox{#1}{#2}% +} + +\newcommand{\@robustHeight}[1]{% + \eifstrequal{\cssVerticalAlign}{top}% + {\raisebox{0pt}[0pt][\cssHeight]{#1}}% + {\eifstrequal{\cssVerticalAlign}{middle}% + {\raisebox{0pt}[0.5\cssHeight][0.5\cssHeight]{#1}}% + {\eifstrequal{\cssVerticalAlign}{baseline}% + {\raisebox{0pt}[\dimexpr\cssHeight-\depth\relax][\depth]{#1}}% + {\raisebox{0pt}[\cssHeight][0pt]{#1}}% bottom + }}% +} + +\newcommand{\@robustTableParbox}[2]{% + \eifstrequal{\cssVerticalAlign}{top}{\def\@cssValign{t}}% + {\eifstrequal{\cssVerticalAlign}{center}{\def\@cssValign{c}}% + {\eifstrequal{\cssVerticalAlign}{middle}{\def\@cssValign{c}}}% + {\def\@cssValign{b}}}% + \ifdim\cssHeight=1sp% + \parbox[\@cssValign]{#1}{#2}% + \else% + \parbox[\@cssValign][\cssHeight]{#1}{#2}% + \fi% +} + +\newcommand{\@cssInlinePadding}{% + \eifstrequal{\cssBackgroundColor}{}{}% + {\eifstrequal{\cssBackgroundColor}{white}{}% + {\strsplit{\cssBackgroundColor}% + \eifstrequal{\strhead}{\#}% + {\cssWrapCmd{\protect\colorbox[HTML]{\strtail}}}% + {\cssWrapCmd{\@robustColorbox{\cssBackgroundColor}}}% + }% + }% + \@needframefalse% + \eifstrequal{\cssBorderTopStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderBottomStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderLeftStyle}{none}{}{\@needframetrue}% + \eifstrequal{\cssBorderRightStyle}{none}{}{\@needframetrue}% + \if@needframe% + \setlength{\fboxrule}{\cssBorderWidth}% + \ifdim\cssWidth=1sp% + \cssWrapCmd{\fbox}% + \else + \cssWrapCmd{\@robustFramebox{\cssWidth}}% + \fi + \else + \ifdim\cssWidth=1sp\else + \cssWrapCmd{\@robustMakebox{\cssWidth}}% + \fi + \fi + % height? + \ifdim\cssHeight=1sp\else\cssWrapCmd{\@robustHeight}\fi + % raisebox? + \eifstrequal{\cssDisplay}{inline}{% + \eifstrequal{\cssVerticalAlign}{}{}% + {\eifstrequal{\cssVerticalAlign}{top}{}% + {\eifstrequal{\cssVerticalAlign}{bottom}{}% + {\eifstrequal{\cssVerticalAlign}{middle}{}% + {\eifstrequal{\cssVerticalAlign}{baseline}{}% + {\cssWrapCmd{\@robustRaisebox{\cssVerticalAlign}}% + }}}}}% + }{}% + % padding + \if@needframe + \setlength{\fboxsep}{\cssPaddingTop}% todo: define our own box so we can set paddingtop/bot separately + \ifdim\cssPaddingBottom>\fboxsep\setlength{\fboxsep}{\cssPaddingBottom}\fi + \ifdim\cssPaddingLeft=\fboxsep\else\hspace*{\dimexpr\cssPaddingLeft-\fboxsep\relax}\fi + \ifdim\cssPaddingRight=\fboxsep\else\hspace*{\dimexpr\cssPaddingRight-\fboxsep\relax}\fi + \else + \ifdim\cssPaddingLeft=0pt\else\cssDoBefore{\hspace*{\cssPaddingLeft}}\fi + \ifdim\cssPaddingRight=0pt\else\cssDoAfter{\hspace*{\cssPaddingRight}}\fi + \ifdim\cssPaddingBottom=0pt\else\cssDoBefore{\protect\rule[-\cssPaddingBottom]{0pt}{\cssPaddingBottom}}\fi + \ifdim\cssPaddingTop=0pt\else\cssDoBefore{\protect\rule{0pt}{\dimexpr\cssPaddingTop+0.8em\relax}}\fi + \fi +} + +%------------------------------------------------------------- +% css: Textalign, textindent etc +%------------------------------------------------------------- + +\cssNewLengthKey{css}{text-indent}{\cssTextIndent} +\cssNewKey{css}{text-align}{\cssTextAlign}{justify} +\cssNewLengthKey{css}{line-height}{\cssLineHeight} +\cssNewKey{css}{float}{\cssFloat}{} + +\DeclareRobustCommand{\@robustColor}[1]{% + \cssDefNormalizeColor{@fcolor}{#1}\color{\@fcolor}% +} +\DeclareRobustCommand{\@robustColorbox}[2]{% + \cssDefNormalizeColor{@bcolor}{#1}\colorbox{\@bcolor}{#2}% +} + + +\newcommand{\@cssProcessText}{% + \eifstrequal{\cssDisplay}{block}% + {\@cssBlockText}% + {\eifstrequal{\cssDisplay}{block-inline}% + {\@cssBlockText}% + {\eifstrequal{\cssDisplay}{table-cell}% + {\@cssBlockText}% + {\@cssInlineText}% + }}} + +\newcommand{\@cssBlockText}{% + \eifstrequal{\cssId}{}{}{\label{\cssId}}% set label + \eifstrequal{\cssTextAlign}{left}% + {\cssDoBefore{\protect\raggedright}}% + {\eifstrequal{\cssTextAlign}{right}% + {\cssDoBefore{\protect\raggedleft}}% + {\eifstrequal{\cssTextAlign}{center}% + {\cssDoBefore{\protect\centering}}% + {}}}% + \ifdim\cssLineHeight=0pt\else\setlength{\baselineskip}{\cssLineHeight}\fi + \noindent\ifdim\cssTextIndent=0pt\else\hspace*{\cssTextIndent}\fi +} + +\newcommand{\@cssInlineText}{% + \eifstrequal{\cssId}{}{}{\label{\cssId}}% set label + \eifstrequal{\cssFloat}{left}% + {\cssDoAfter{\hspace*{\fill}}}% + {\eifstrequal{\cssFloat}{right}% + {\cssDoBefore{\hspace*{\fill}}}% + {\eifstrequal{\cssFloat}{center}% + {\cssDoAfter{\hspace*{\fill}}\cssDoBefore{\hspace*{\fill}}}% + {}}}% + \ifdim\cssLineHeight=0pt\else\cssDoBefore{\rule{0pt}{\cssLineHeight}}\fi +} + +%------------------------------------------------------------- +% css: Font attributes +%------------------------------------------------------------- + +\cssNewKey{css}{font-weight}{\cssFontWeight}{} +\cssNewKey{css}{font-variant}{\cssFontVariant}{} +\cssNewKey{css}{font-style}{\cssFontStyle}{} +\cssNewKey{css}{font-size}{\cssFontSize}{} +\cssNewKey{css}{font-family}{\cssFontFamily}{} +\cssNewKey{css}{color}{\cssColor}{} +\cssNewKey{css}{penalty}{\cssPenalty}{} + +\newcommand{\@cssProcessFont}{% + % font family + \edef\@fontFamily{\cssFontFamily}% + \@for\@ii:=\cssFontFamily\do{% find the last argument in a comma separated list + \edef\@fontFamily{\@ii}% + }% + \eifstrequal{\@fontFamily}{}{}% quick test + {\eifstrequal{\@fontFamily}{monospace}% + {\cssDoBefore\ttfamily}% + {\eifstrequal{\@fontFamily}{serif}% + {\cssDoBefore\rmfamily}% + {\eifstrequal{\@fontFamily}{sans-serif}% + {\cssDoBefore\sffamily}% + {\eifstrequal{\@fontFamily}{normal}% + {\cssDoBefore\rmfamily}% + {\cssDoBefore{\fontspec{\@fontFamily}}}% + }}}}% + % + \eifstrequal{\cssFontWeight}{bold}% + {\cssDoBefore\bfseries}% + {\eifstrequal{\cssFontWeight}{normal}% + {\cssDoBefore\mdseries}% + {}}% + \eifstrequal{\cssFontVariant}{small-caps}% + {\cssDoBefore\scshape}% + {\eifstrequal{\cssFontVariant}{normal}% + {\cssDoBefore\upshape}% + {}}% + \eifstrequal{\cssFontStyle}{italic}% + {\cssDoBefore\itshape\hspace{-0.2ex}}% + {\eifstrequal{\cssFontStyle}{oblique}% + {\cssDoBefore\slshape}% + {\eifstrequal{\cssFontStyle}{normal}% + {\cssDoBefore\upshape}% + {}}}% + \eifstrequal{\cssFontSize}{}{}% quick test + {\eifstrequal{\cssFontSize}{xx-small}% + {\cssDoBefore\tiny}% + {\eifstrequal{\cssFontSize}{x-small}% + {\cssDoBefore\scriptsize}% + {\eifstrequal{\cssFontSize}{small}% + {\cssDoBefore\small}% + {\eifstrequal{\cssFontSize}{medium}% + {\cssDoBefore\normalsize}% + {\eifstrequal{\cssFontSize}{large}% + {\cssDoBefore\large}% + {\eifstrequal{\cssFontSize}{x-large}% + {\cssDoBefore\Large}% + {\eifstrequal{\cssFontSize}{xx-large}% + {\cssDoBefore\LARGE}% + {}}}}}}}}% + % + \eifstrequal{\cssColor}{}{}% + {\strsplit{\cssColor}% + \eifstrequal{\strhead}{\#}% + {\cssDoBefore{\protect\color[HTML]{\strtail}}}% + {\cssDoBefore{\@robustColor{\cssColor}}}% + }% + % + \eifstrequal{\cssPenalty}{}{}% + {\penalty \cssPenalty\relax}% +} + + + + +%------------------------------------------------------------- +% Generic css rules for certain classes, ids, or elements +%------------------------------------------------------------- +\newcommand{\cssRule}[3]{% + \@for\@ii:=#2\do{% + \csappto{@rule@#1@\@ii}{,#3}% + }% +}% + +\newcommand{\cssRuleDo}[3]{% + \@for\@ii:=#2\do{% + \csappto{@ruleDo@#1@\@ii}{#3}% + }% +}% + + +\newcommand{\@cssApplyRulesFor}[3]{% + \@for\@ii:=#3\do{% + \ifcsmacro{@rule@#1@\@ii}{% + \edef\@args{\csname @rule@#1@\@ii\endcsname}% + \@expandafter{\setkeys{#2}}{\@args}% + }{}% + }% +} + +\newcommand{\@cssApplyDoRulesFor}[3]{% + \@for\@ii:=#3\do{% + \ifcsmacro{@ruleDo@#1@\@ii}{% + \csname @ruleDo@#1@\@ii\endcsname% + }{}% + }% +} + +\newcommand{\cssIfHasClass}[3]{% + \def\@found{}% + \@for\@ii:=\cssClass\do{% + \@for\@cname:=#1\do{% + \eeifstrequal{\@ii}{\@cname}{% + \def\@found{true}% + }{}% + }% + }% + \ifdefvoid{\@found}{#3}{#2}% +} + + +\newcommand{\cssClassRule}[2]{\cssRule{class}{#1}{#2}} +\newcommand{\cssElemRule}[2]{\cssRule{elem}{#1}{#2}} +\newcommand{\cssIdRule}[2]{\cssRule{id}{#1}{#2}} + +\cssNewListKeyX{cssx}{class}{\cssClass}{}{\@cssApplyRulesFor{class}{css}} +\cssNewKeyX{cssx}{elem}{\cssElem}{}{\@cssApplyRulesFor{elem}{css}} +\cssNewKeyX{cssx}{id}{\cssId}{}{\@cssApplyRulesFor{id}{css}} + + +\newcommand{\cssClassRuleDo}[2]{\cssRuleDo{class}{#1}{#2}} +\newcommand{\cssClassRuleCmd}[2]{\cssClassRuleDo{#1}{\cssWrapCmd{#2}}} +\newcommand{\cssClassRuleDoBefore}[2]{\cssClassRuleDo{#1}{\cssDoBefore{#2}}} +\newcommand{\cssClassRuleDoAfter}[2]{\cssClassRuleDo{#1}{\cssDoAfter{#2}}} +\newcommand{\cssClassRuleEnv}[2]{\cssClassRuleDoBefore{#1}{\begin{#2}}\cssClassRuleDoAfter{#1}{#2}} + +\newcommand{\cssElemRuleDo}[2]{\cssRuleDo{class}{#1}{#2}} +\newcommand{\cssElemRuleCmd}[2]{\cssElemRuleDo{#1}{\cssWrapCmd{#2}}} +\newcommand{\cssElemRuleDoBefore}[2]{\cssElemRuleDo{#1}{\cssDoBefore{#2}}} +\newcommand{\cssElemRuleDoAfter}[2]{\cssElemRuleDo{#1}{\cssDoAfter{#2}}} +\newcommand{\cssElemRuleEnv}[2]{\cssElemRuleDo{#1}{\cssDoEnv{#2}}} + +\newcommand{\@cssClassDoRules}{\@cssApplyDoRulesFor{class}{css}{\cssClass}} +\newcommand{\@cssElemDoRules}{% + \@cssApplyDoRulesFor{elem}{css}{\cssElem}% + \@cssApplyDoRulesFor{id}{css}{\cssId}% +} + +\newcommand{\cssParentClass}{} +\newcommand{\cssParentClassRule}[2]{\cssRule{parentclass}{#1}{#2}} + + +%------------------------------------------------------------- +% +%------------------------------------------------------------- + +\newenvironment{cssBlockX}[2]% + {\@cssReset\@cssUseEnv\@cssProcessAttrs{#1}{#2}% + \@cssElemDoRules% + \@cssProcessMargins\@cssProcessPadding% + \@cssClassDoRules% + \@cssProcessText\@cssProcessFont% + \@cssApplyBefore}% + {\@cssApplyAfter} + +\newenvironment{cssBlock}[1][]% + {\begin{cssBlockX}{}{#1}}{\end{cssBlockX}} + +\newcommand{\cssInlineX}[4]% + {\@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline,#1}{#2}% + \@cssElemDoRules% + \@cssProcessMargins\@cssProcessPadding% + \@cssClassDoRules% + #3% + \@cssProcessText\@cssProcessFont% + \@cssApplyCmd{#4}% + }% + +\newcommand{\cssInline}[2][]{\cssInlineX{}{#1}{}{#2}} +\newcommand{\cssInlineCmd}[3][]{\cssInlineX{}{#1}{\cssWrapCmd{#2}}{#3}} + +\newcommand{\cssNewBlockElem}[3]{% + \newenvironment{#1}[1][]{\begin{cssBlockX}{elem=#2,#3}{##1}}{\end{cssBlockX}}} + +\newcommand{\cssNewInlineElem}[3]{% + \newcommand{#1}[2][]{\cssInlineX{elem=#2,#3}{##1}{}{##2}}} + + +\newcommand{\cssNewInlineElemCmd}[4]{% + \newcommand{#1}[2][]{\cssInlineX{elem=#2,#3}{##1}{\cssWrapCmd{#4}}{##2}}} + +\newcommand{\cssInitKeys}[1]{% + \@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline}{#1}% +} + +% cssText is just for font attributes; no padding or margins +\newcommand{\cssTextX}[2]% + {\@cssReset\@cssUseCmd\@cssProcessAttrs{display=inline}{#1}% + \@cssElemDoRules% + %\@cssProcessMargins\@cssProcessPadding% + \@cssClassDoRules% + \@cssProcessText\@cssProcessFont% + \@cssApplyCmd{#2}% + }% + + +\newcommand{\cssText}[2][]{\cssTextX{#1}{#2}} -- cgit v1.2.3