%% algpseudocodex.sty
%% Copyright 2017, 2020-2023, 2025 Christian Matt
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% 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.3c or later is part of all distributions of LaTeX
% version 2008-05-04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Christian Matt.
%
% This work consists of the files algpseudocodex.sty and algpseudocodex.tex.


% Pseudocodex algorithmic style
% Based on Szasz Janos' algpseudocode.sty

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{algpseudocodex}[2025-04-16 v1.2.0 pseudocode typesetting]
\RequirePackage{kvoptions}
\RequirePackage{algorithmicx}
\RequirePackage{etoolbox}
\RequirePackage{fifo-stack}
\RequirePackage{varwidth}
\RequirePackage{tabto}
\RequirePackage{totcount}
\RequirePackage{tikz}
\usetikzlibrary{calc,fit,tikzmark}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Package options
%
\SetupKeyvalOptions{%
	family=algpx,%
	prefix=algpx@%
}

\DeclareBoolOption[true]{noEnd}% don't print end if etc.
\DeclareBoolOption[true]{indLines}% show indent guide lines
\DeclareBoolOption[true]{spaceRequire}% adds vertical space before \Require if not in first line
\DeclareBoolOption[true]{italicComments}% italicise comments
\DeclareBoolOption[true]{rightComments}% right justify comments
\DeclareStringOption[gray]{commentColor}% color of comments
\DeclareStringOption[$\triangleright$~]{beginComment}% print at beginning of comment
\DeclareStringOption[]{endComment}% print at end of comment
\DeclareStringOption[$\triangleright$~]{beginLComment}% print at beginning of long comment
\DeclareStringOption[~$\triangleleft$]{endLComment}% print at end of long comment
\ProcessLocalKeyvalOptions*


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Styles
%
\tikzset{%
	algpxDefaultBox/.style={draw},%
	algpxIndentLine/.style={draw=gray,very thin}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declarations
%
\algnewlanguage{pseudocodex}
\alglanguage{pseudocodex}

% \tikzmark is only available on next compilation; the following command immediately after using it
\newcommand{\@tikzmarkNow}[2][]{\tikz[overlay,remember picture] \node[#1] (#2) {};}

\long\def\@ifnodedefined#1#2#3{%
	\@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}

\newlength{\algpx@codeBoxInnerSep}% distance between box and its content
\newlength{\algpx@codeBoxSep}% distance between nested boxes
\newlength{\algpx@codeBoxOuterSep}% additional space before and after box

% the following lengths related to indent lines are set when opening an algorithmic environment to reflect to current font size
\newlength{\algpx@indShiftX}% indent line shifted right by that amount from beginning of line
\newlength{\algpx@indStartShiftY}% start of indent line shifted up by that amount from beginning of line
\newlength{\algpx@indEndShiftY}% end of indent line shifted up by that amount from beginning of line (only if noEnd=false, otherwise no shift)
\newlength{\algpx@indXLineLength}% length of horizonal line drawn at end when noEnd=true
\newlength{\algpx@minIndDist}% minimum distance between start and end of indent line to draw line
\newlength{\algpx@oldPos}
\newlength{\algpx@newPos}
\newlength{\algpx@tmpLen}% length to be used for various things
\newlength{\algpx@currentLineskiplimit}% used to restore lineskiplimit in varwidth
\newlength{\algpx@currentLineskip}% used to restore lineskip in varwidth
\newlength{\algpx@indStartY}
\newlength{\algpx@indEndY}
\newlength{\algpx@indStartX}% x coordinate of indent line
\newlength{\algpx@extraShiftX}% current line is shifted by this amount right
\newlength{\algpx@minTopPageHeight}% minimum for setting height of first line on page (used, e.g., to draw indent lines on page break)
\newlength{\algpx@minBotPageDepth}% minimum for setting depth of last line on page (used, e.g., to draw indent lines on page break)

\setlength{\algpx@codeBoxInnerSep}{2pt}
\setlength{\algpx@codeBoxSep}{3pt}
\setlength{\algpx@codeBoxOuterSep}{1pt}
\settoheight{\algpx@minTopPageHeight}{\footnotesize9}% account for line numbers, which use \footnotesize
\settodepth{\algpx@minBotPageDepth}{\footnotesize9}% account for line numbers, which use \footnotesize

\newbool{algpx@firstLine}
\newbool{algpx@setNorth}% whether codeBoxNorth should be set
\newbool{algpx@executeEndVarwidth}
\newbool{algpx@adjustHeight}
\newbool{algpx@restorePrevdepth}
\newbool{algpx@hasCheckedPageBreak}% whether checkPageBreak has been executed in current environment
\newbool{algpx@indJustEnded}% true after end with noend
\newbool{algpx@pageJustBroken}%

\newcounter{algpx@codeBoxCount}% number of already created code boxes. Used to fill algpx@startNewCodeBoxQueue
\newcounter{algpx@nestedCBoxCount}
\newcounter{algpx@startedBoxesCount}
\newcounter{algpx@endedBoxesCount}
\newcounter{algpx@nestedBoxedStringCount}
\newcounter{algpx@nestedBoxedStringMaxCount}
\newcounter{algpx@indentCount}
\newcounter{algpx@lastIndentEnded}
\newcounter{algpx@pageCount}% counter of "pages" (columns in multi column format); incremented when page break is detected
\newcounter{algpx@tmpCount}% temporary counter

\FSCreate{algpx@startNewCodeBoxQueue}{0}% queue of code boxes to be created on next \State, \If etc. Only stores index of box (0 is value of top if empty; should not be relevant)
\FSCreate{algpx@codeBoxStack}{0}
\FSCreate{algpx@codeBoxStackTmp}{0}
\FSCreate{algpx@indentStack}{0}
\FSCreate{algpx@indentStackTmp}{0}

\newsavebox{\algpx@boxedStringBox}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Macros for boxes around code
%
% Draw a box. First parameter is style, others are coordinates (north, west, east, south)
\newcommand{\algpx@drawCodeBox}[5]{%
	\tikz[overlay,remember picture]{%
		\node[inner sep=\algpx@codeBoxInnerSep,#1,fit={(pic cs:#2) (pic cs:#3) (pic cs:#4) (pic cs:#5)}] {};%
	}%
}

% execute after \State, \If etc.
\newcommand{\algpx@startCodeCommand}{%
	\algpx@startCodeCommandX{}{}%
}

% execute before printing end if etc.
\newcommand{\algpx@startEndBlockCommand}{%
	% add space for indentation because of how ALG@nested is computed
	\algpx@startCodeCommandX[1]{}{\hspace*{\algorithmicindent}}%
}

% extended version of \algpx@startCodeCommand
% first argument 1 if executed in \algpx@startEndBlockCommand
% second argument is printed before content
% third argument is used to reserve space after contents (for end symbol of long comments)
\newcommand{\algpx@startCodeCommandX}[3][0]{%
	\setbool{algpx@indJustEnded}{false}%
	\setcounter{algpx@startedBoxesCount}{0}%
	\setcounter{algpx@endedBoxesCount}{0}%
	\setcounter{algpx@nestedBoxedStringMaxCount}{0}%
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{%
		\FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}%
		\algpx@drawCodeBox{algpx@codeBoxStyle-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}%
		\FSPop{algpx@startNewCodeBoxQueue}%
		\setbool{algpx@setNorth}{true}%
		\stepcounter{algpx@startedBoxesCount}%
	}%
	\algpx@setCodeBoxWest%
	% check for page break only if indent line is open because page breaks are only used for this
	\ifboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@indentStack}}}}{%
		\algpx@checkPageBreak[#1]%
	}{}%
	\setbool{algpx@firstLine}{false}%
	\setbool{algpx@executeEndVarwidth}{true}%
	#2%
	% create box from here to end of line, leaving space for #3
	\settowidth{\algpx@extraShiftX}{#2}% remember that line actually starts further right than last box
	\settowidth{\algpx@tmpLen}{#3}%
	\setlength{\algpx@currentLineskiplimit}{\lineskiplimit}% remember value of lineskiplimit
	\setlength{\algpx@currentLineskip}{\lineskip}% remember value of lineskip
	\begin{varwidth}[t]{\dimexpr \linewidth - \algpx@extraShiftX - \algpx@tmpLen - \algorithmicindent * \numexpr \value{ALG@nested} - 1 \relax \relax}%
	\setlength{\lineskiplimit}{\algpx@currentLineskiplimit}% restore lineskiplimit value
	\setlength{\lineskip}{\algpx@currentLineskip}% restore lineskip value
}

% executed before \State, \If etc., i.e., at end of previous line
% first argument 1 if after \EndIf etc. and noend
\newcommand{\algpx@endCodeCommand}[1][0]{%
	\ifbool{algpx@executeEndVarwidth}{%
		\par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982
		\end{varwidth}\setbox0=\lastbox\usebox0%
		\setbool{algpx@executeEndVarwidth}{false}%
		\setbool{algpx@adjustHeight}{true}%
		\setbool{algpx@restorePrevdepth}{true}%
	}{}%
	\ifbool{algpx@setNorth}{%
		% todo: north should not be set again if highest element in current line is BoxedString
		\algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line
		\setbool{algpx@setNorth}{false}%
	}{}%
	\algpx@setCodeBoxEast%
	% remember position of ending line and possibly set north of page
	% not necessary if no indent lines are open or just ended (because EndIf with noEnd cannot break page)
	\ifboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@indentStack}}} and not bool{algpx@indJustEnded}}{%
		\algpx@setLineEndPos%
	}{}%
	\ifbool{algpx@adjustHeight}{%
		% todo: if highest or deepest element in current line is BoxedString, \ht0 or \dp0 should be adjusted for different sep values
		\algpx@addBoxSpacing{\value{algpx@startedBoxesCount}}{\the\ht0}{\value{algpx@endedBoxesCount}}{\the\dp0}%
		\setbool{algpx@adjustHeight}{false}%
	}{}%
	\ifboolexpr{bool{algpx@restorePrevdepth} and test{\ifstrequal{#1}{0}}}{%
		\par\prevdepth\algpx@pdtemp%
		\setbool{algpx@restorePrevdepth}{false}%
	}{}%
}

% Checks whether current line starts on new page (or column) by comparing y position with previous line.
% If so, draws indent lines neither starting nor ending on this page.
% Optional argument is 1 if executed on end block with noEnd=false.
%
% Note: We do not rely on \iftikzmarkonpage because, e.g., in double-column format, lines can be on the same page,
% but we want to consider them to be on different pages.
\newcommand{\algpx@checkPageBreak}[1][0]{%
	\ifbool{algpx@hasCheckedPageBreak}{% first line of code cannot be on new page
		% extract y positions of previous line
		\tikz[overlay,remember picture]{%
			\pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@currentStartYPos}{center}}%
			\global\algpx@oldPos=\algpx@oldPos%
		}%
		% current pos is 0, so if last pos is less than that, we are on new page
		\ifdimcomp{\algpx@oldPos}{<}{0ex}{%
			% set south of previous page to y pos last saved in \algpx@setLineEndPos
			\tikz[overlay,remember picture]{%
				\tikzmark{algpx@pageSouth-\thealgpx@pageCount}{(algpx@currentEndYPos)}%
			}%
			\stepcounter{algpx@pageCount}%
			\setbool{algpx@pageJustBroken}{true}%
			% all currently open indent lines have started on earlier page.
			% Draw full line from top to bottom for all of those not ending on this page either
			\algpx@drawIndentLinesOnPageBreak[#1]%
		}{%
			\tikz[overlay,remember picture]{}% dummy to keep in sync
			\tikz[overlay,remember picture]{}% dummy to keep in sync (inside drawIndentLinesOnPageBreak)
		}%
	}{}%
	\@tikzmarkNow{algpx@currentStartYPos}% save y position of current line to compare next time
	\setbool{algpx@hasCheckedPageBreak}{true}%
}

% Remember current position as south of page and set north of current page if page was just broken.
\newcommand{\algpx@setLineEndPos}{%
	% save y position of current line shifted down the depth of current line to later use for pageSouth coordinate in \algpx@checkPageBreak
	% shift down at least by \algpx@minBotPageDepth
	\ifdimcomp{\the\dp0}{<}{\algpx@minBotPageDepth}{%
		\@tikzmarkNow[yshift=-\algpx@minBotPageDepth]{algpx@currentEndYPos}%
	}{%
		\@tikzmarkNow[yshift=-\the\dp0]{algpx@currentEndYPos}%
	}%
	% right after pagebreak, set north of current page
	\ifbool{algpx@pageJustBroken}{%
		% shift to beginning of line and also shift up by height of current line, but last least \algpx@minTopPageHeight
		% also shift to left by \wd0 (width of last box, i.e., of line in varwidth) + \algpx@extraShiftX to get x position at beginning of line
		\tikz[overlay,remember picture]{%
			\ifdimcomp{\the\ht0}{<}{\algpx@minTopPageHeight}{%
				\coordinate (algpx@pageNorth) at (-\wd0 - \algpx@extraShiftX,\algpx@minTopPageHeight);%
			}{%
				\coordinate (algpx@pageNorth) at (-\wd0 - \algpx@extraShiftX,\the\ht0);%
			}%
			\tikzmark{algpx@pageNorth-\thealgpx@pageCount}{(algpx@pageNorth)}%
		}%
		\setbool{algpx@pageJustBroken}{false}%
	}{%
		\tikz[overlay,remember picture]{}% dummy to keep in sync
	}%
}

% set algpx@codeBoxNorthMax of current box and all ancestors; argument is amount to shift up from current baseline
\newcommand{\algpx@setCodeBoxNorth}[1]{%
	\setcounter{algpx@nestedCBoxCount}{0}%
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{%
		\FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp
		\@ifnodedefined{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{%
			% get current position; shift according to nest-level to ensure nested boxes don't collide
			\@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthHere}%
			% extract y-coordinate of previously stored north
			\tikz[overlay,remember picture]{%
				\pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}{center}}%
				\pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxNorthHere}{center}}%
				\global\algpx@oldPos=\algpx@oldPos%
				\global\algpx@newPos=\algpx@newPos%
			}%
			\ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{%
				% new y is greater than old one, so set it
				\@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}%
			}{%
				\@tikzmarkNow{algpx@codeBoxNorthDummy}% set something to keep in sync
			}%
		}{%
			\@tikzmarkNow[yshift=\dimexpr #1 + \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack}}%
		}%
		\FSPop{algpx@codeBoxStack}%
		\stepcounter{algpx@nestedCBoxCount}%
	}%
	% restore stack from tmp
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{%
		\FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}%
		\FSPop{algpx@codeBoxStackTmp}%
	}%
}


% set algpx@codeBoxSouthMax of current box and all ancestors; argument is amount to shift down from current baseline
\newcommand{\algpx@setCodeBoxSouth}[1]{%
	\setcounter{algpx@nestedCBoxCount}{0}%
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{%
		\FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp
		\@ifnodedefined{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{%
			% get current position; shift according to nest-level to ensure nested boxes don't collide
			\@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthHere}%
			% extract y-coordinate of previously stored south
			\tikz[overlay,remember picture]{%
				\pgfextracty{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}{center}}%
				\pgfextracty{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxSouthHere}{center}}%
				\global\algpx@oldPos=\algpx@oldPos%
				\global\algpx@newPos=\algpx@newPos%
			}%
			\ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{%
				% new y is less than old one, so set it
				\@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}%
			}{%
				\@tikzmarkNow{algpx@codeBoxSouthDummy}% set something to keep in sync
			}%
		}{%
			\@tikzmarkNow[yshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack}}%
		}%
		\FSPop{algpx@codeBoxStack}%
		\stepcounter{algpx@nestedCBoxCount}%
	}%
	% restore stack from tmp
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{%
		\FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}%
		\FSPop{algpx@codeBoxStackTmp}%
	}%
}

% set algpx@codeBoxWestMax of current box and all ancestors; argument is amount to shift left from current position
\newcommand{\algpx@setCodeBoxWest}[1][0pt]{%
	\setcounter{algpx@nestedCBoxCount}{0}%
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{%
		\FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp
		\@ifnodedefined{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{%
			% get current position; shift according to nest-level to ensure nested boxes don't collide
			\@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestHere}%
			% extract x-coordinate of previously stored west
			\tikz[overlay,remember picture]{%
				\pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}{center}}%
				\pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxWestHere}{center}}%
				\global\algpx@oldPos=\algpx@oldPos%
				\global\algpx@newPos=\algpx@newPos%
			}%
			\ifdimcomp{\algpx@oldPos}{>}{\algpx@newPos}{%
				% new x is smaller than old one, so set it
				\@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}%
			}{%
				\@tikzmarkNow{algpx@codeBoxWestDummy}% set something to keep in sync
			}%
		}{%
			\@tikzmarkNow[xshift=\dimexpr -#1 -\algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack}}%
		}%
		\FSPop{algpx@codeBoxStack}%
		\stepcounter{algpx@nestedCBoxCount}%
	}%
	% restore stack from tmp
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{%
		\FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}%
		\FSPop{algpx@codeBoxStackTmp}%
	}%
}

% set algpx@codeBoxEastMax of current box and all ancestors
\newcommand{\algpx@setCodeBoxEast}{%
	\setcounter{algpx@nestedCBoxCount}{0}%
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}}}{%
		\FSPush{algpx@codeBoxStackTmp}{\FSTop{algpx@codeBoxStack}}% copy stack to tmp
		\@ifnodedefined{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{%
			% get current position; shift according to nest-level to ensure nested boxes don't collide
			\@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastHere}%
			% extract x-coordinate of previously stored east
			\tikz[overlay,remember picture]{%
				\pgfextractx{\algpx@oldPos}{\pgfpointanchor{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}{center}}%
				\pgfextractx{\algpx@newPos}{\pgfpointanchor{algpx@codeBoxEastHere}{center}}%
				\global\algpx@oldPos=\algpx@oldPos%
				\global\algpx@newPos=\algpx@newPos%
			}%
			\ifdimcomp{\algpx@oldPos}{<}{\algpx@newPos}{%
				% new x is greater than old one, so set it
				\@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}%
			}{%
				\@tikzmarkNow{algpx@codeBoxEastDummy}% set something to keep in sync
			}%
		}{%
			\@tikzmarkNow[xshift=\dimexpr \algpx@codeBoxSep * \value{algpx@nestedCBoxCount}\relax]{algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack}}%
		}%
		\FSPop{algpx@codeBoxStack}%
		\stepcounter{algpx@nestedCBoxCount}%
	}%
	% restore stack from tmp
	\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStackTmp}}}}{%
		\FSPush{algpx@codeBoxStack}{\FSTop{algpx@codeBoxStackTmp}}%
		\FSPop{algpx@codeBoxStackTmp}%
	}%
}

% Set coordinates of box on top of algpx@codeBoxStack to maximal reported values.
% This ensures, e.g., that the right edge of the box is after the longest line inside.
\newcommand{\algpx@setBoxesToStoredMax}{%
	\tikz[overlay,remember picture]{%
		\tikzmark{algpx@codeBoxNorth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxNorthMax-\FSTop{algpx@codeBoxStack})}%
		\tikzmark{algpx@codeBoxSouth-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxSouthMax-\FSTop{algpx@codeBoxStack})}%
		\tikzmark{algpx@codeBoxWest-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxWestMax-\FSTop{algpx@codeBoxStack})}%
		\tikzmark{algpx@codeBoxEast-\FSTop{algpx@codeBoxStack}}{(algpx@codeBoxEastMax-\FSTop{algpx@codeBoxStack})}%
	}%
}

% add some space above and below box; more if several boxes are nested
% first argument: number of boxes above
% second argument: height of content
% third argument: number of boxes below
% fourth argument: depth of content
\newcommand{\algpx@addBoxSpacing}[4]{%
	\ifnumcomp{0}{<}{#1}{%
		\rule{0pt}{\dimexpr #2 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#1 - 1))\relax}%
	}{}%
	\ifnumcomp{0}{<}{#3}{%
		\rule[\dimexpr -#4 - \algpx@codeBoxInnerSep - \algpx@codeBoxOuterSep - (\algpx@codeBoxSep * (#3 - 1))\relax]{0pt}{\dimexpr #4 + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep + (\algpx@codeBoxSep * (#3 - 1))\relax}% negative offset equal to height to draw line down from baseline
	}{}%
}

% Begin a new code box here.
% Must be followed by \State, \If, \For etc.
% (optional) argument is style of box
\newcommand{\BeginBox}[1][algpxDefaultBox]{%
	\ignorespaces%
	\FSUnshift{algpx@startNewCodeBoxQueue}{\thealgpx@codeBoxCount}% add to queue; processed by \algpx@startCodeCommand
	%globally set tikz style (https://tex.stackexchange.com/a/47918)
	\begingroup%
		\globaldefs=1\relax%
		\pgfqkeys{/tikz}{algpx@codeBoxStyle-\thealgpx@codeBoxCount/.style={#1}}%
	\endgroup%
	\stepcounter{algpx@codeBoxCount}%
	\ignorespaces%
}

% End one open code box. Fails if no box open (i.e., if algpx@codeBoxStack is empty).
\newcommand{\EndBox}{%
	\ignorespaces%
	\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{%
		\PackageError{algpseudocodex}{BeginBox must be followed by State, If, For, etc. Use BoxedString instead}{}%
		\FSClear{algpx@startNewCodeBoxQueue}%
	}{%
		\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}{%
			\unskip%
			\ifbool{algpx@executeEndVarwidth}{%
				\par\xdef\algpx@pdtemp{\the\prevdepth}% see https://tex.stackexchange.com/a/34982
				\end{varwidth}\setbox0=\lastbox\usebox0%
				\setbool{algpx@executeEndVarwidth}{false}%
				\setbool{algpx@adjustHeight}{true}%
				\setbool{algpx@restorePrevdepth}{true}%
			}{}%
			\ifbool{algpx@setNorth}{%
				\algpx@setCodeBoxNorth{\the\ht0}% set north here shifted by height of current line
				\setbool{algpx@setNorth}{false}%
			}{}%
			\algpx@setCodeBoxEast%
			\ifbool{algpx@indJustEnded}{%
				\algpx@setCodeBoxSouth{0pt}% set south here, don't shift after end with noEnd
				% add space after boxes. Otherwise done by endCodeCommand, but this is not executed after End with noEnd
				\algpx@addBoxSpacing{\value{algpx@startedBoxesCount}}{0pt}{\numexpr \value{algpx@endedBoxesCount} + 1 \relax}{0pt}%
			}{%
				\algpx@setCodeBoxSouth{\the\dp0}% set south here shifted by depth of current line
			}%
			%adjust stored prevdepth for ended boxes
			\ifnumcomp{0}{<}{\value{algpx@endedBoxesCount}}{%
				\edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxSep \relax}%
			}{%
				\edef\algpx@pdtemp{\dimexpr \algpx@pdtemp + \algpx@codeBoxInnerSep + \algpx@codeBoxOuterSep \relax}%
			}%
			\algpx@setBoxesToStoredMax%
			\FSPop{algpx@codeBoxStack}%
			\stepcounter{algpx@endedBoxesCount}%
		}{%
			\PackageError{algpseudocodex}{No box to end}{}%
		}%
	}%
	\ignorespaces%
}

% Draw box within a single line of code.
% (Optional) first argument is style of the box.
% Second argument is the string to print inside the box.
\newcommand{\BoxedString}[2][algpxDefaultBox]{%
	\ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{%
		\setcounter{algpx@nestedBoxedStringMaxCount}{0}% reset max count for new boxes
	}{}%
	\stepcounter{algpx@nestedBoxedStringCount}%
	\ifnumcomp{\value{algpx@nestedBoxedStringMaxCount}}{<}{\value{algpx@nestedBoxedStringCount}}{%
		\setcounter{algpx@nestedBoxedStringMaxCount}{\value{algpx@nestedBoxedStringCount}}%
	}{}%
	\algpx@drawCodeBox{#1}{algpx@codeBoxNorth-\thealgpx@codeBoxCount}{algpx@codeBoxWest-\thealgpx@codeBoxCount}{algpx@codeBoxEast-\thealgpx@codeBoxCount}{algpx@codeBoxSouth-\thealgpx@codeBoxCount}%
	\FSPush{algpx@codeBoxStack}{\thealgpx@codeBoxCount}%
	\stepcounter{algpx@codeBoxCount}%
	\algpx@setCodeBoxWest%
	\ifmmode%
		% This works in equation but not in align / displaystyle etc. gets lost
		\savebox{\algpx@boxedStringBox}{$\m@th#2$}%
		\usebox{\algpx@boxedStringBox}%
	\else%
		\savebox{\algpx@boxedStringBox}{#2}%
		\usebox{\algpx@boxedStringBox}%
	\fi%
	\algpx@setCodeBoxEast%
	\algpx@setCodeBoxNorth{\the\ht\algpx@boxedStringBox}%
	\algpx@setCodeBoxSouth{\the\dp\algpx@boxedStringBox}%
	\algpx@setBoxesToStoredMax%
	\FSPop{algpx@codeBoxStack}%
	\addtocounter{algpx@nestedBoxedStringCount}{-1}% BoxedString ends here
	\ifnumcomp{\value{algpx@nestedBoxedStringCount}}{=}{0}{%
		\algpx@addBoxSpacing{\value{algpx@nestedBoxedStringMaxCount}}{\the\ht\algpx@boxedStringBox}{\value{algpx@nestedBoxedStringMaxCount}}{\the\dp\algpx@boxedStringBox}%
	}{}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Macros for indentation  lines
%
% start indented block
\newcommand{\algpx@startIndent}{%
	\ifbool{algpx@indLines}{%
		% Define counter for the page on which this indent line ends.
		% The use of totcount ensures the last value is preserved during compilations and thus can be used before setting it.
		% expansion is needed because name contains variable, see
		% https://tex.stackexchange.com/questions/517559/why-cant-the-name-of-a-totcounter-be-defined-with-a-variable
		\expanded{\noexpand\newtotcounter{algpx@indentEndPage-\thealgpx@indentCount}}%
		% set start coordinate here and draw indent line
		% Note: Draw already here because endIndent could already be called on next page if end is at last line of page.
		\tikz[overlay,remember picture]{%
			\coordinate (startPos) at (\algpx@indShiftX,\algpx@indStartShiftY);
			\algpx@drawIndentLine{\thealgpx@indentCount}{startPos}%
		}%
		\FSPush{algpx@indentStack}{\thealgpx@indentCount}%
		\stepcounter{algpx@indentCount}%
	}{}%
}

% end of indented block
% optional argument 1 means that only interrupted by else, 2 means ended with until
\newcommand{\algpx@endIndent}[1][0]{%
	\ifbool{algpx@indLines}{%
		% remember on which page indent line ends (remembered through compiliations because we use totcount)
		\setcounter{algpx@indentEndPage-\FSTop{algpx@indentStack}}{\value{algpx@pageCount}}%
		\tikz[overlay,remember picture]{%
			\ifboolexpr{bool{algpx@indJustEnded} and test{\ifstrequal{#1}{0}}}{%
				% if another line has just ended, use same coordinates as for previous end
				% to this end, remember index of previous end to use
				\expanded{\noexpand\newtotcounter{algpx@indentEndCoordIndex-\FSTop{algpx@indentStack}}}%
				\setcounter{algpx@indentEndCoordIndex-\FSTop{algpx@indentStack}}{\thealgpx@lastIndentEnded}%
			}{%
				% if not just ended, use current position (0,0) as end
				\ifboolexpr{bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{%
					% Draw additional line to right if noend and line is not interrupted and move down by current line depth.
					% Note: we are now at the end of the line, so the x position is too far right.
					% We solve this in \algpx@drawIndentLine by going at most \algpx@indShiftX to the right.
					% Adjusting here would require access to the start position and thus an additional compilation.
					\coordinate (algpx@indentEndCoord) at (\algpx@indShiftX+\algpx@indXLineLength,-\the\dp0);%
				}{%
					% if using end or interrupted by else etc., use current position shifted by default values
					\coordinate (algpx@indentEndCoord) at (\algpx@indShiftX,\algpx@indEndShiftY);%
				}%
				% remember end position using \tikzmark so it can be accessed by \algpx@startIndent before
				\tikzmark{algpx@indentEnd-\FSTop{algpx@indentStack}}{(algpx@indentEndCoord)}%
			}%
		}%
	}{}%
	% set indJustEnded even if indLines are not drawn; also used for EndBox
	\ifboolexpr{not bool{algpx@indJustEnded} and bool{algpx@noEnd} and test{\ifstrequal{#1}{0}}}{%
		\setbool{algpx@indJustEnded}{true}%
		\ifbool{algpx@indLines}{%
			\setcounter{algpx@lastIndentEnded}{\FSTop{algpx@indentStack}}%
		}{}%
	}{}%
	\ifbool{algpx@indLines}{%
		\FSPop{algpx@indentStack}%
		\ifstrequal{#1}{1}{%
			\algpx@startIndent% start new line if only interrupted
		}{}%
	}{}%
}

% Draw indent line with index #1 and start coordinate (#2).
% To be called inside a TikZ picture.
\newcommand{\algpx@drawIndentLine}[2]{%
	\ifnumcomp{\totvalue{algpx@indentEndPage-#1}}{>}{\value{algpx@pageCount}}{%
		% if indentation does not end on the same page, draw line to end of page with x position of start
		\coordinate (algpx@indentEndCoord) at (#2 |- {pic cs:algpx@pageSouth-\thealgpx@pageCount});%
	}{%
		% otherwise, indentation ends on same page
		\@ifundefined{c@algpx@indentEndCoordIndex-#1@totc}{%
			% if no indentEndCoordIndex is stored, just use stored end position
			\coordinate (algpx@indentEndCoord) at (pic cs:algpx@indentEnd-#1);%
		}{%
			% if indentEndCoordIndex is defined, another line has just ended and we use the same y coordinates as for previous end
			\coordinate (algpx@indentEndCoord) at (pic cs:algpx@indentEnd-\the\totvalue{algpx@indentEndCoordIndex-#1});%
		}%
	}{}%
	% Only draw if there is minimum distance between start and end
	\pgfextracty{\algpx@indStartY}{\pgfpointanchor{#2}{center}}%
	\pgfextracty{\algpx@indEndY}{\pgfpointanchor{algpx@indentEndCoord}{center}}%
	\ifdimcomp{\algpx@indStartY - \algpx@indEndY}{>}{\algpx@minIndDist}{%
		% draw in straight lines from start position (#2) to end coordinate, but with x position at most start + \algpx@indXLineLength since end position is set at end of line in \algpx@endIndent
		\draw[algpxIndentLine] let \p1=(#2), \p2=(algpx@indentEndCoord) in (#2) |- ({min(\x2, \x1 + \algpx@indXLineLength)}, \y2);%
	}{}%
}

% For all open indent lines not ending on current page, draw from top to bottom of page
% Optional argument is 1 if executed on end block with noEnd=false.
\newcommand{\algpx@drawIndentLinesOnPageBreak}[1][0]{%
	\tikz[overlay,remember picture]{%
		% iterate over all open indent lines
		\ifstrequal{#1}{0}{%
			\setcounter{algpx@tmpCount}{0}% tmp counter to count interations
		}{%
			% if ending block here, the last indentation has already ended and line won't be drawn
			% start counting at -1 to get correct indentation of later ending lines.
			\setcounter{algpx@tmpCount}{-1}%
		}%
		\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@indentStack}}}}{%
			\FSPush{algpx@indentStackTmp}{\FSTop{algpx@indentStack}}% copy stack to tmp
			\stepcounter{algpx@tmpCount}%
			% draw line to bottom of page
			% set beginning of line to north of page (with x set to beginning of line, see \algpx@checkPageBreak)
			% shifted by the number indentations
			\coordinate (startPos) at ($(pic cs:algpx@pageNorth-\thealgpx@pageCount) - (\dimexpr \algorithmicindent * \value{algpx@tmpCount} - \algpx@indShiftX \relax, 0ex)$);%
			\algpx@drawIndentLine{\FSTop{algpx@indentStack}}{startPos}%
			% finally remove top element
			\FSPop{algpx@indentStack}%
		}%
		% restore stack from tmp
		\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@indentStackTmp}}}}{%
			\FSPush{algpx@indentStack}{\FSTop{algpx@indentStackTmp}}%
			\FSPop{algpx@indentStackTmp}%
		}%
	}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Keywords
%
\algnewcommand\algorithmicend{\textbf{end}}
\algnewcommand\algorithmicdo{\textbf{do}}
\algnewcommand\algorithmicwhile{\textbf{while}}
\algnewcommand\algorithmicfor{\textbf{for}}
\algnewcommand\algorithmicforall{\textbf{for all}}
\algnewcommand\algorithmicloop{\textbf{loop}}
\algnewcommand\algorithmicrepeat{\textbf{repeat}}
\algnewcommand\algorithmicuntil{\textbf{until}}
\algnewcommand\algorithmicprocedure{\textbf{procedure}}
\algnewcommand\algorithmicfunction{\textbf{function}}
\algnewcommand\algorithmicif{\textbf{if}}
\algnewcommand\algorithmicthen{\textbf{then}}
\algnewcommand\algorithmicelse{\textbf{else}}
\algnewcommand\algorithmicrequire{\textbf{Require:}}
\algnewcommand\algorithmicensure{\textbf{Ensure:}}
\algnewcommand\algorithmicreturn{\textbf{return}}
\algnewcommand\algorithmicoutput{\textbf{output}}
\algnewcommand\algorithmicstructure{\textbf{structure}}
\algnewcommand\algorithmicclass{\textbf{class}}
\algnewcommand\algorithmicproperties{\textbf{properties}}
\algnewcommand\algorithmicmethods{\textbf{methods}}
\algnewcommand\textproc{\textsc}% font for procedure/function names
\algnewcommand\textstruc{\textsc}% font for structure and class names


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Loops, conditional statements, and functions
%
\algdef{SE}[WHILE]{While}{EndWhile}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicwhile\ #1\ \algorithmicdo%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicwhile%
}
\algdef{SE}[FOR]{For}{EndFor}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicfor\ #1\ \algorithmicdo%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicfor%
}
\algdef{S}[FOR]{ForAll}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicforall\ #1\ \algorithmicdo%
}
\algdef{SE}[LOOP]{Loop}{EndLoop}{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicloop%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicloop%
}
\algdef{SE}[REPEAT]{Repeat}{Until}{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicrepeat%
}[1]{%
	\algpx@startEndBlockCommand\algpx@endIndent[2]\algorithmicuntil\ #1%
}
\algdef{SE}[IF]{If}{EndIf}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicif\ #1\ \algorithmicthen%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicif%
}
\algdef{C}[IF]{IF}{ElsIf}[1]{%
	\algpx@startCodeCommand\algpx@endIndent[1]\algorithmicelse\ \algorithmicif\ #1\ \algorithmicthen%
}
\algdef{Ce}[ELSE]{IF}{Else}{EndIf}{%
	\algpx@startCodeCommand\algpx@endIndent[1]\algorithmicelse%
}
\algdef{SE}[PROCEDURE]{Procedure}{EndProcedure}[2]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicprocedure\ \textproc{#1}\ifstrempty{#2}{}{(#2)}%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicprocedure%
}
\algdef{SE}[FUNCTION]{Function}{EndFunction}[2]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicfunction\ \textproc{#1}\ifstrempty{#2}{}{(#2)}%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicfunction%
}
\algdef{SE}[STRUCTURE]{Structure}{EndStructure}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicstructure\ \textstruc{#1}%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicstructure%
}
\algdef{SE}[CLASS]{Class}{EndClass}[1]{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicclass\ \textstruc{#1}%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicclass%
}
\algdef{SE}[PROPERTIES]{Properties}{EndProperties}{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicproperties%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicproperties%
}
\algdef{SE}[METHODS]{Methods}{EndMethods}{%
	\algpx@startCodeCommand\algpx@startIndent\algorithmicmethods%
}{%
	\algpx@startEndBlockCommand\algpx@endIndent\algorithmicend\ \algorithmicmethods%
}

\ifbool{algpx@noEnd}{%
	\algtext*{EndWhile}%
	\algtext*{EndFor}%
	\algtext*{EndLoop}%
	\algtext*{EndIf}%
	\algtext*{EndProcedure}%
	\algtext*{EndFunction}%
	\algtext*{EndStructure}%
	\algtext*{EndClass}%
	\algtext*{EndProperties}%
	\algtext*{EndMethods}%
	%
	% end indent line before end command
	\pretocmd{\EndWhile}{\algpx@endIndent}{}{}%
	\pretocmd{\EndFor}{\algpx@endIndent}{}{}%
	\pretocmd{\EndLoop}{\algpx@endIndent}{}{}%
	\pretocmd{\EndIf}{\algpx@endIndent}{}{}%
	\pretocmd{\EndProcedure}{\algpx@endIndent}{}{}%
	\pretocmd{\EndFunction}{\algpx@endIndent}{}{}%
	\pretocmd{\EndStructure}{\algpx@endIndent}{}{}%
	\pretocmd{\EndClass}{\algpx@endIndent}{}{}%
	\pretocmd{\EndProperties}{\algpx@endIndent}{}{}%
	\pretocmd{\EndMethods}{\algpx@endIndent}{}{}%
}{}%

% execute \algpx@endCodeCommand before \State, \If etc.
\pretocmd{\State}{\algpx@endCodeCommand}{}{}
\pretocmd{\While}{\algpx@endCodeCommand}{}{}
\pretocmd{\For}{\algpx@endCodeCommand}{}{}
\pretocmd{\ForAll}{\algpx@endCodeCommand}{}{}
\pretocmd{\Loop}{\algpx@endCodeCommand}{}{}
\pretocmd{\Repeat}{\algpx@endCodeCommand}{}{}
\pretocmd{\Until}{\algpx@endCodeCommand}{}{}
\pretocmd{\If}{\algpx@endCodeCommand}{}{}
\pretocmd{\ElsIf}{\algpx@endCodeCommand}{}{}
\pretocmd{\Else}{\algpx@endCodeCommand}{}{}
\pretocmd{\Procedure}{\algpx@endCodeCommand}{}{}
\pretocmd{\Function}{\algpx@endCodeCommand}{}{}
\pretocmd{\Structure}{\algpx@endCodeCommand}{}{}
\pretocmd{\Class}{\algpx@endCodeCommand}{}{}
\pretocmd{\Properties}{\algpx@endCodeCommand}{}{}
\pretocmd{\Methods}{\algpx@endCodeCommand}{}{}

% for end commands that may not be printed, tell endCodeCommand whether we are using noEnd
\ifbool{algpx@noEnd}{%
	\pretocmd{\EndWhile}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndFor}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndLoop}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndIf}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndProcedure}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndFunction}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndStructure}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndClass}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndProperties}{\algpx@endCodeCommand[1]}{}{}%
	\pretocmd{\EndMethods}{\algpx@endCodeCommand[1]}{}{}%
}{%
	\pretocmd{\EndWhile}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndFor}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndLoop}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndIf}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndProcedure}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndFunction}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndStructure}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndClass}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndProperties}{\algpx@endCodeCommand[0]}{}{}%
	\pretocmd{\EndMethods}{\algpx@endCodeCommand[0]}{}{}%
}%

% execute \algpx@startCodeCommand after \State (this is done for loops etc. inside the definitions above)
\apptocmd{\State}{\algpx@startCodeCommand}{}{}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Other declarations
%

% dirty hack: execute drawing in argument of item and rest of \algpx@startCodeCommand outside
% argument: text in item[.]
\newcommand{\algpx@drawInItem}[1]{%
	\item[%
		\whileboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{%
			\FSPush{algpx@codeBoxStack}{\FSTop{algpx@startNewCodeBoxQueue}}%
			\algpx@drawCodeBox{algpx@codeBoxStyle-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxNorth-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxWest-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxEast-\FSTop{algpx@startNewCodeBoxQueue}}{algpx@codeBoxSouth-\FSTop{algpx@startNewCodeBoxQueue}}%
			\FSPop{algpx@startNewCodeBoxQueue}%
			\stepcounter{algpx@startedBoxesCount}%
		}%
		#1%
	]%
	\setbool{algpx@indJustEnded}{false}%
	\setcounter{algpx@startedBoxesCount}{0}%
	\setcounter{algpx@endedBoxesCount}{0}%
	\setcounter{algpx@nestedBoxedStringMaxCount}{0}%
	\settowidth{\algpx@tmpLen}{#1}%
	\algpx@setCodeBoxWest[\dimexpr \labelsep + \algpx@tmpLen \relax]%
	\setbool{algpx@firstLine}{false}%
	\setbool{algpx@executeEndVarwidth}{true}%
	\setlength{\algpx@currentLineskiplimit}{\lineskiplimit}% remember value of lineskiplimit
	\setlength{\algpx@currentLineskip}{\lineskip}% remember value of lineskip
	\begin{varwidth}[t]{\dimexpr \linewidth - \labelsep - \algpx@tmpLen + \leftmargin \relax}%
	\setlength{\lineskiplimit}{\algpx@currentLineskiplimit}% restore lineskiplimit value
	\setlength{\lineskip}{\algpx@currentLineskip}% restore lineskip value
	\settoheight{\algpx@tmpLen}{#1}%
	\rule{0pt}{\algpx@tmpLen}%
}

\algnewcommand\Require{%
	\algpx@endCodeCommand%
	\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}%
	\ifboolexpr{bool{algpx@spaceRequire} and not bool{algpx@firstLine}}{%
		\medskip%
	}{}%
	\algpx@drawInItem{\algorithmicrequire}%
}

\algnewcommand\Ensure{%
	\algpx@endCodeCommand%
	\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}{\setbool{algpx@setNorth}{true}}{}%
	\algpx@drawInItem{\algorithmicensure}%
}

\algnewcommand\Return{\algorithmicreturn{} }
\algnewcommand\Output{\algorithmicoutput{} }
\algnewcommand\Call[2]{\textproc{#1}\ifstrempty{#2}{}{(#2)}}

%% internal methods to format comment
% format according to comment format
\newcommand{\algpx@commentFormat}[1]{%
	\ifbool{algpx@italicComments}{%
		\textit{\textcolor{\algpx@commentColor}{#1}}%
	}{%
		\textcolor{\algpx@commentColor}{#1}%
	}%
}

% get string for inline comment including begin and end markers
\newcommand{\algpx@commentString}[1]{%
	\algpx@commentFormat{\algpx@beginComment#1\algpx@endComment}%
}

% redefine \Comment
\algrenewcomment[1]{%
	\ifbool{algpx@rightComments}{%
		\settowidth{\algpx@tmpLen}{\algpx@commentString{#1}}% set temp variable to width of comment
		\tabto{\CurrentLineWidth}% this saves current position in \TabPrevPos and fixes spacing up to here
		\ifdimcomp{\algpx@tmpLen}{<}{\dimexpr \linewidth - \TabPrevPos \relax}{% check whether comment fits on line
			\tabto{\dimexpr \linewidth - \algpx@tmpLen \relax}% move position to right justify text
			\algpx@commentString{#1}% print comment
		}{%
			\algpx@commentString{#1}% if it doesn't fit, just print normally, allowing line break
		}%
	}{%
		\algpx@commentString{#1}% just print normally if not right justified
	}%
	\ignorespaces%
}%

% Long comment starting on new line.
% Can span several lines and in contrast to \Comment, never right justified.
\algdef{SL}[LCOMMENT]{LComment}{0}[1]{%
	\algpx@startCodeCommandX{\algpx@commentFormat{\algpx@beginLComment}}{\algpx@commentFormat{\algpx@endLComment}}%
	\algpx@commentFormat{#1}% print actual comment
	\tabto{\CurrentLineWidth}% this saves current position in \TabPrevPos and fixes spacing up to here
	\setlength{\algpx@tmpLen}{\dimexpr \linewidth - \TabPrevPos \relax}% set to remaining space on line
	\makebox[0pt][l]{% start box here that takes no space (otherwise impacts spacing of text before)
		\rule{\algpx@tmpLen}{0pt}% draw invisible rule from beginning of line until end of comment text
		\algpx@commentFormat{\algpx@endLComment}% print end comment at the end
		\algpx@setCodeBoxEast% since this takes 0 space, we have to set east of code box here explicitly
	}%
}%

\pretocmd{\LComment}{\algpx@endCodeCommand}{}{}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Execute at beginning and end of algorithmic environment
%
\AtBeginEnvironment{algorithmic}{%
	\setbool{algpx@firstLine}{true}%
	\setbool{algpx@setNorth}{false}%
	\setbool{algpx@executeEndVarwidth}{false}%
	\setbool{algpx@adjustHeight}{false}%
	\setbool{algpx@restorePrevdepth}{false}%
	\setbool{algpx@hasCheckedPageBreak}{false}%
	\setbool{algpx@pageJustBroken}{false}%
	\setcounter{algpx@startedBoxesCount}{0}%
	\setcounter{algpx@endedBoxesCount}{0}%
	%
	% Set lengths here to use correct font sizes
	\setlength{\algpx@indShiftX}{0.12em}%
	\setlength{\algpx@indStartShiftY}{-0.8ex}%
	\setlength{\algpx@indEndShiftY}{2.0ex}%
	\setlength{\algpx@indXLineLength}{0.5em}%
	\setlength{\algpx@minIndDist}{0.7ex}%
}

\AtEndEnvironment{algorithmic}{%
	\algpx@endCodeCommand%
	% Error checking
	\ifboolexpr{test{\ifnumcomp{0}{<}{\FSSize{algpx@codeBoxStack}}} or test {\ifnumcomp{0}{<}{\FSSize{algpx@startNewCodeBoxQueue}}}}{%
		\PackageError{algpseudocodex}{Some boxes have not ended}{}%
	}{}%
}
