[Tex/LaTex] Global scope or permanent length or savebox

grouping

I am trying to save a minipage width and height in one environment, and use these dimensions in a subsequent environment of mine, to make a picture environment.
The idea is to create a picture on the right of the minipage using the rest of the \columnwidth, and with the same height as the minipage on the left.
The problem is, as far as I understand, that neither the lengths nor the \savebox'es set within the first environment survive to the next one, as they are subject to scoping rules of LaTeX.

So my question is, how can save dimensions (or the box) in one environment and use them in another?

Update: here is (non-working) example using \global:

\documentclass{article}
\usepackage{calc}
\usepackage{picture}

\newsavebox{\questiontextbox}
\newsavebox{\questionpicturebox}
\newlength{\questiontextheight}

\newenvironment{questiontext}[1]%
{\begin{lrbox}{\questiontextbox}%
\begin{minipage}[t]{#1}}%
{\end{minipage}\end{lrbox}%
\noindent\usebox{\questiontextbox}%
\settoheight{\questiontextheight}{\usebox{\questiontextbox}}% ****
\global\setlength{\questiontextheight}{\questiontextheight}}

\newenvironment{questionpicture}[1]%
{\begin{lrbox}{\questionpicturebox}%
\setlength{\unitlength}{1cm}%
\begin{picture}(#1-\fboxsep-\fboxsep,\questiontextheight)}%
{\end{picture}\end{lrbox}%
\fbox{\raisebox{-\questiontextheight}{\usebox{\questionpicturebox}}}}

\begin{document}
\begin{questiontext}{0.2\columnwidth}
There must be some text here so I made it up to fill more than just a
single line.
\end{questiontext}%
\begin{questionpicture}{0.8\columnwidth}
\put(0.5,0.5){\circle{0.4}}
\end{questionpicture}

\end{document}

The \fbox is there only to visualize that the picture height is only two \fboxsep's. I tried to put \global before \settoheight in the line marked with ****, which does not work, either. No idea what I am doing wrong; could the packages calc or picture (which is needed to use real dimensions) prevent proper \global behaviour?

the result

Best Answer

There is a primitive \global that makes a following TeX assignment global. So you can use \global\setbox and \global\def = \gdef. In LaTeX as David Carlisle kindly points out you may get away with \global\setlength in some circumstances, but in general it is not guaranteed to work, and loading packages such as calc in fact prevents it working. One work around is to use an intermediate global TeX assignment of the result of a calculation via \global\len=\len after the \setlength:

Sample output

\documentclass[a4paper]{article}

\usepackage{calc}
\newlength{\mylength}
\newlength{\myglength}
\newlength{\myllength}

\begin{document}
\setlength{\mylength}{10pt}
\setlength{\myglength}{10pt}
\setlength{\myllength}{10pt}

\verb+\mylength+ is \the\mylength.
\verb+\myglength+ is \the\myglength.
\verb+\myllength+ is \the\myllength.

\bigskip

\begin{minipage}{0.9\linewidth}
\setlength{\mylength}{20pt}
\setlength{\myglength}{20pt}
\global\setlength{\myllength}{20pt} % Doesn't work when calc is loaded
\global\myglength=\myglength
Minipage start

\verb+\mylength+ is \the\mylength.
\verb+\myglength+ is \the\myglength.
\verb+\myllength+ is \the\myllength.

Minigage end
\end{minipage}

\bigskip

\verb+\mylength+ is \the\mylength.
\verb+\myglength+ is \the\myglength.
\verb+\myllength+ is \the\myllength.
\end{document}

In the specific example you now give, you need to get hold of the totalheight of the box, to get a picture of the same height and this then needs to be shifted down by the depth of the minipage. The above \global tricks will now work:

Sample application output

\documentclass{article}

\usepackage{calc}
\usepackage{picture}
\usepackage{ragged2e}

\newsavebox{\questiontextbox}
\newsavebox{\questionpicturebox}
\newlength{\questiontexttotalheight}
\newlength{\questiontextdepth}

\newenvironment{questiontext}[1]%
{\begin{lrbox}{\questiontextbox}%
  \begin{minipage}[t]{#1}}%
{\end{minipage}\end{lrbox}%
  \noindent\usebox{\questiontextbox}%
  \settototalheight{\questiontexttotalheight}{\usebox{\questiontextbox}}%
  \settodepth{\questiontextdepth}{\usebox{\questiontextbox}}%
  \global\questiontexttotalheight=\questiontexttotalheight
  \global\questiontextdepth=\questiontextdepth}

\newenvironment{questionpicture}[1]%
{\begin{lrbox}{\questionpicturebox}%
  \setlength{\unitlength}{1cm}%
  \begin{picture}(#1-\fboxsep-\fboxsep-0.8pt,\questiontexttotalheight)}%
{\end{picture}\end{lrbox}%
  \fbox{\raisebox{-\questiontextdepth}{\usebox{\questionpicturebox}}}}

\begin{document}
\begin{questiontext}{0.2\columnwidth}
  \RaggedRight There must be some text here so I made it up to fill more than just
  a single line.
\end{questiontext}%
\begin{questionpicture}{0.8\columnwidth}
  \put(0.5,0.5){\circle{0.4}}
\end{questionpicture}

\end{document}

I have changed a couple of extra things in your code. Firstly, the width of your \fbox has not only the \fboxsep but two rules 0.4pt wide, so you need to substract 0.8pt more to avoid an overfull box. Secondly, the narrow column on the left is better set ragged right, using the ragged2e package provides the \RaggedRight command which is less drastic than standard \raggedright.

Related Question