JIndex
JAbsValue::PrepareToRender
	(
	const JExprRenderer&	renderer,
	const JPoint&			upperLeft,
	const JSize				fontSize,
	JExprRectList*			rectList
	)
{
	const JSize barWidth = renderer.GetVertBarWidth();

	// get rectangle for our argument

	JPoint argUpperLeft = upperLeft;
	argUpperLeft.x += barWidth;

	JFunction* arg = GetArg();
	const JIndex argIndex =
		arg->PrepareToRender(renderer, argUpperLeft, fontSize, rectList);

	// calculate our rectangle

	JRect ourRect  = rectList->GetRect(argIndex);
	ourRect.left  -= barWidth;
	ourRect.right += barWidth;

	// save our rectangle

	const JCoordinate ourMidline = rectList->GetMidline(argIndex);
	return rectList->AddRect(ourRect, ourMidline, fontSize, this);
}
void
JAbsValue::Render
	(
	const JExprRenderer& renderer,
	const JExprRectList& rectList
	)
	const
{
	// find ourselves in the list

	JIndex ourIndex;
	const JBoolean found = rectList.FindFunction(this, &ourIndex);
	assert( found );

	const JRect ourRect = rectList.GetRect(ourIndex);

	// draw ourselves

	renderer.DrawVertBar(ourRect.left, ourRect.top, ourRect.height());
	(GetArg())->Render(renderer, rectList);
	renderer.DrawVertBar(ourRect.right - renderer.GetVertBarWidth(),
						 ourRect.top, ourRect.height());
}
void
JParallel::Render
	(
	const JExprRenderer& renderer,
	const JExprRectList& rectList
	)
	const
{
	// find ourselves in the list

	JIndex ourIndex;
	const JBoolean found = rectList.FindFunction(this, &ourIndex);
	assert( found );

	const JRect ourRect = rectList.GetRect(ourIndex);
	const JCoordinate ourMidline = rectList.GetMidline(ourIndex);
	const JSize fontSize = rectList.GetFontSize(ourIndex);

	// draw ourselves

	const JSize spaceWidth = renderer.GetStringWidth(fontSize, " ");
	const JSize barWidth   = renderer.GetVertBarWidth();
	const JSize lineHeight = renderer.GetLineHeight(fontSize);

	JSize maxBarLength;
	if (((JSize) ourRect.height()) > lineHeight)
		{
		maxBarLength = JLFloor(ourRect.height()/2.0);
		}
	else
		{
		maxBarLength = ourRect.height();
		}
	JSize barLength;
	if (ourMidline > ourRect.ycenter())
		{
		barLength = 2*(ourRect.bottom - ourMidline);
		}
	else
		{
		barLength = 2*(ourMidline - ourRect.top);
		}
	if (barLength > maxBarLength)
		{
		barLength = maxBarLength;
		}
	const JCoordinate barTop = ourMidline - barLength/2;

	const JSize argCount = GetArgCount();
	for (JIndex i=1; i<=argCount; i++)
		{
		const JFunction* arg = GetArg(i);
		arg->Render(renderer, rectList);

		JIndex argIndex;
		const JBoolean found = rectList.FindFunction(arg, &argIndex);
		assert( found );
		const JRect argRect = rectList.GetRect(argIndex);
		JCoordinate h = argRect.right + spaceWidth;

		if (ParenthesizeArgForRender(*this, *arg))
			{
			renderer.DrawParentheses(argRect);
			h += renderer.GetParenthesisWidth(argRect.height());
			}

		if (i < argCount)
			{
			renderer.DrawVertBar(h, barTop, barLength);
			renderer.DrawVertBar(h + barWidth, barTop, barLength);
			}
		}
}
JIndex
JParallel::PrepareToRender
	(
	const JExprRenderer&	renderer,
	const JPoint&			upperLeft,
	const JSize				fontSize,
	JExprRectList*			rectList
	)
{
	// intialize our rectangle and midline

	JPoint argUpperLeft = upperLeft;

	JRect ourRect(upperLeft, argUpperLeft);
	ourRect.bottom += renderer.GetLineHeight(fontSize);
	JCoordinate ourMidline = (ourRect.top + ourRect.bottom)/2;
	const JCoordinate origMidline = ourMidline;

	// get rectangle for each argument

	const JSize opWidth =
		2*(renderer.GetStringWidth(fontSize, " ") + renderer.GetVertBarWidth());
	const JSize argCount = GetArgCount();
	{
	for (JIndex i=1; i<=argCount; i++)
		{
		JFunction* arg = GetArg(i);
		const JIndex argIndex =
			arg->PrepareToRender(renderer, argUpperLeft, fontSize, rectList);
		JRect argRect  = rectList->GetRect(argIndex);
		argUpperLeft.x = argRect.right + opWidth;

		if (ParenthesizeArgForRender(*this, *arg))
			{
			const JSize parenWidth = renderer.GetParenthesisWidth(argRect.height());
			rectList->ShiftRect(argIndex, parenWidth, 0);
			argRect = rectList->GetRect(argIndex);
			argUpperLeft.x += 2*parenWidth;
			ourRect.right   = argRect.right + parenWidth;
			}

		ourRect = JCovering(ourRect, argRect);
		const JCoordinate argMidline = rectList->GetMidline(argIndex);
		if (argMidline > ourMidline)
			{
			ourMidline = argMidline;
			}
		}
	}

	// adjust the argument rectangles so all the midlines are the same
	// (ourMidline is guaranteed to stay constant)

	if (argCount > 1 && ourMidline > origMidline)
		{
		for (JIndex i=1; i<=argCount; i++)
			{
			const JFunction* arg = GetArg(i);
			JIndex argIndex;
			const JBoolean found = rectList->FindFunction(arg, &argIndex);
			assert( found );
			rectList->SetMidline(argIndex, ourMidline);
			ourRect = JCovering(ourRect, rectList->GetRect(argIndex));
			}
		}

	// save our rectangle

	return rectList->AddRect(ourRect, ourMidline, fontSize, this);
}