1

I'm creating .tex file for batch creating visit cards. There is a logo in the top left corner and the baseline for the holder's is above the logo bottom edge. In 90 % of cases, the name and titles fits in the column dedicated to the content. In 99 %, the name and titles do not collide with the logo. But there is one in 100 of people to cause problems...

In following case if the name is too long it is broken to two lines.

\parbox[b]{47.5mm}{\flushright%
  {\fontsize{9}{9}\selectfont\textbf{#1}}\\% Typeset the name
  {\fontsize{5}{5}\selectfont\#2}\\% ... Typeset next line
}

If it is modified with \makebox the overflowing name is single line and right aligned but if it is too long it overflows in the logo.

\parbox[b]{47.5mm}{\flushright{%
  \makebox[47.5mm][r]{\fontsize{9}{9}\selectfont\textbf{#1}}\\% Typeset the name
  {\fontsize{5}{5}\selectfont#2}\\% ... Typeset next line
}}

Is there a way how to measure the width of a box to be placed? Something like:

\If{\LengthOf{#1}>50mm}%
{% True branch
\makebox[47.5mm][r]{#1}% Typeset the content
\hspace{50mm-\LengthOf{#1}}% Add a negative glue
\rule{0mm}{0mm}% Add zero width box for the \hspace to work
}%
{% Else branch
\makebox[47.5mm][r]{#1}}

Or a some smart \foobox[width][alignment][overflow alignment]{content} that will be <alignment> aligned, when the content fits in, but the content overflows the box in <direction> way? Say \foobox[...][r][l]{...} typesets:
| narrow|
|text that fits|
|text that is t|oo wide to fit

  • please fix your example so that people can run and debug the issue. – David Carlisle May 17 '18 at 18:13
  • \makebox[47.5][r] would be an error (the first argument should be a length) \#2 would typeset # and 2 – David Carlisle May 17 '18 at 18:41
  • @DavidCarlisle Thanks for your time and comments. The second is a typo and forgotten units - should be all mm. And I'll add the surroundings to make it working example tomorrow. – Crowley May 17 '18 at 18:51
1

This is easy to achieve for a single line. It is also possible to do this in a parbox, but this requires manual line breaks to work properly, which is not good for automation. Doing this automatically is much harder.

The following defines a macro \cutbox with an optional argument for settings and a mandatory one for the text. The possible keys are

  • align sets the alignment for cut and overflow lines. It can take the values rr (align right overflow right), ll (align left overflow left), rl (align right overflow left) and lr (align left overflow right).
  • cutlines sets the number of short lines from the top.
  • cutwidth sets the maximum length of the cut lines.
  • overflowwidth sets the maximum length for overflow lines.
  • paralign sets the alignment for the surrounding \parbox. The possible values are t, b and c.

The resulting \parbox is cutwidth wide and lines in there may overflow up to overflowwidth - cutwidth.

The result (the lines here are just for testing):

Short and long names:

enter image description here

Whole paragraph (with cutlines=3):

enter image description here

The code:

\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz} % just for drawing some test lines
\usepackage{xkeyval} % for the keys

\makeatletter
% one line adjusted right overflow to the right
\newcommand*{\onelinerr}[1]{%
    \hbox to \cutbox@cutwidth{\hskip0pt plus 1fill\relax #1\hskip 0pt minus 1fill}%
}
% one line adjusted left overflow to the left
\newcommand*{\onelinell}[1]{%
    \hbox to \cutbox@cutwidth{\hskip0pt minus 1fill\relax #1\hskip 0pt plus 1fill}%
}
% one line adjusted right overflow to the left
\newcommand*{\onelinerl}[1]{%
    \hbox to \cutbox@cutwidth{\hss #1}%
}
% one line adjusted left overflow to the right
\newcommand*{\onelinelr}[1]{%
    \hbox to \cutbox@cutwidth{#1\hss}%
}
% some counters and lengths
\newcount\cutbox@cutlines
\newcount\cutbox@cutlines@cnt
\newdimen\cutbox@cutwidth
\newdimen\cutbox@overflowwidth
\newbox\cutbox@testbox
\newtoks\cutbox@resttoks
% the keys
\define@choicekey{cutbox}{paralign}[\cutbox@paralign]{t,b,c}[b]{}
\define@choicekey{cutbox}{align}[\cutbox@align]{rr,ll,rl,lr}[ll]{}
\define@key{cutbox}{cutlines}[1]{\cutbox@cutlines=#1\relax}
\define@key{cutbox}{cutwidth}[47.5mm]{\cutbox@cutwidth=#1\relax}
\define@key{cutbox}{overflowwidth}[95mm]{\cutbox@overflowwidth=#1\relax}
% initialize the keys
\setkeys{cutbox}{paralign=c,align=ll,cutlines=1,cutwidth=47.5mm,overflowwidth=95mm}
% output the remaining non cut lines
\newcommand*{\cutbox@output@restrr}{%
    \hbox to \cutbox@cutwidth{\parbox[t]{\cutbox@overflowwidth}{\raggedright\the\cutbox@resttoks}\hss}%
}
\newcommand*{\cutbox@output@restll}{%
    \hbox to \cutbox@cutwidth{\hss\parbox[t]{\cutbox@overflowwidth}{\raggedleft\the\cutbox@resttoks}}%
}
\let\cutbox@output@restrl\cutbox@output@restll
\let\cutbox@output@restlr\cutbox@output@restrr
% main macro
% #1: optional, setup
% #2: the text
\newcommand*{\cutbox}[2][]{%
    \def\@tempa{#2}\ifx\@tempa\@empty
    \else
        \begingroup
        \setkeys{cutbox}{#1}%
        \cutbox@cutlines@cnt=\cutbox@cutlines
        \expandafter\parbox\expandafter[\cutbox@paralign]{\cutbox@cutwidth}{\@cutbox{#2}}%
        \endgroup
    \fi
}
\newcommand*{\@cutbox}[1]{%
    \cutbox@resttoks={#1 }% the space is important
    \loop\ifnum\cutbox@cutlines@cnt>\z@\relax
        \setbox\cutbox@testbox=\hbox{}%
        \expandafter\@cutbox@collectline\the\cutbox@resttoks{} {} \@cutbox@end%
        \ifdim\wd\cutbox@testbox=\z@
            \cutbox@cutlines@cnt\z@
        \else
            \csname oneline\cutbox@align\endcsname{\unhbox\cutbox@testbox}%
        \fi
        \advance\cutbox@cutlines@cnt\m@ne
    \repeat
    \ifnum\cutbox@cutlines@cnt<\@ne
        \setbox\@tempboxa=\hbox{\the\cutbox@resttoks\unskip}%
        \ifdim\wd\@tempboxa=\z@
        \else
            \csname cutbox@output@rest\cutbox@align\endcsname
        \fi
    \fi
}
\def\@cutbox@collectline#1 #2 #3 \@cutbox@end{%
    \setbox\cutbox@testbox=\hbox{#1}%
    \ifdim\wd\cutbox@testbox>\cutbox@cutwidth
        \cutbox@set@resttoks{#2}{#3}%
    \else
        \def\@tempa{#2}\ifx\@tempa\@empty
            \cutbox@set@resttoks{#2}{}%
        \else
            \setbox\@tempboxa=\hbox{ #2}%
            \@tempdima\wd\cutbox@testbox
            \advance\@tempdima\wd\@tempboxa
            \ifdim\@tempdima>\cutbox@cutwidth
                \cutbox@set@resttoks{#2}{#3}%
            \else
                \@cutbox@@collectline#2 #3 \@cutbox@end
            \fi
        \fi
    \fi
}
\def\@cutbox@@collectline#1 #2 #3 \@cutbox@end{%
    \setbox\cutbox@testbox=\hbox{\unhbox\cutbox@testbox\space#1}%
    \def\@tempa{#2}\ifx\@tempa\@empty
        \cutbox@set@resttoks{#2}{}%
    \else
        \setbox\@tempboxa=\hbox{ #2}%
        \@tempdima\wd\cutbox@testbox
        \advance\@tempdima\wd\@tempboxa
        \ifdim\@tempdima>\cutbox@cutwidth
            \cutbox@set@resttoks{#2}{#3}%
        \else
            \@cutbox@@collectline#2 #3 \@cutbox@end
        \fi
    \fi
}
\newcommand*{\cutbox@set@resttoks}[2]{%
    \cutbox@resttoks={#1 }%
    \def\@tempa{#2}\ifx\@tempa\@empty
    \else
        \expandafter\cutbox@resttoks\expandafter=\expandafter{\the\cutbox@resttoks#2\unskip\unskip}%
    \fi
}
% for easier setup
\newcommand*{\setcutbox}[1]{%
    \setkeys{cutbox}{#1}%
}
\makeatother

% just for testing
\parindent0pt
\parskip2ex
\oddsidemargin2in

% setup
\setcutbox{cutwidth=40mm,overflowwidth=80mm}

\begin{document}
% draw lines for testing
\makeatletter
\newdimen\line@left@dist
\line@left@dist\cutbox@overflowwidth
\advance\line@left@dist-\cutbox@cutwidth
\begin{tikzpicture}[overlay]
\draw[blue] (0,0) -- (0,-20);
\draw[blue] (\cutbox@cutwidth,0) -- (\cutbox@cutwidth,-20);
\draw[red] (-\line@left@dist,0) -- (-\line@left@dist,-20);
\draw[red] (\cutbox@overflowwidth,0) -- (\cutbox@overflowwidth,-20);
\end{tikzpicture}
\makeatother

%-----------------------------------------------------------
\texttt{\textbf{align=rr}}

\cutbox[align=rr]{Philip Ackermann}

\cutbox[align=rr]{Prof. Dr. sci.fi. Dr. h.c. Philip Marko Maria Ackermann-Waldvogel}

%-----------------------------------------------------------
\texttt{\textbf{align=ll}}

\cutbox[align=ll]{Philip Ackermann}

\cutbox[align=ll]{Prof. Dr. sci.fi. Dr. h.c. Philip Marko Maria Ackermann-Waldvogel}

%-----------------------------------------------------------
\texttt{\textbf{align=rl}}

\cutbox[align=rl]{Philip Ackermann}

\cutbox[align=rl]{Prof. Dr. sci.fi. Dr. h.c. Philip Marko Maria Ackermann-Waldvogel}

%-----------------------------------------------------------
\texttt{\textbf{align=lr}}

\cutbox[align=lr]{Philip Ackermann}

\cutbox[align=lr]{Prof. Dr. sci.fi. Dr. h.c. Philip Marko Maria Ackermann-Waldvogel}


\newpage
% draw lines for testing
\makeatletter
\begin{tikzpicture}[overlay]
\draw[blue] (0,0) -- (0,-20);
\draw[blue] (\cutbox@cutwidth,0) -- (\cutbox@cutwidth,-20);
\draw[red] (-\line@left@dist,0) -- (-\line@left@dist,-20);
\draw[red] (\cutbox@overflowwidth,0) -- (\cutbox@overflowwidth,-20);
\end{tikzpicture}
\makeatother

% lets cut 3 lines now
\setcutbox{cutlines=3}

% a whole paragraph
\texttt{\textbf{align=rr}}

\cutbox[align=rr]{Quisque ullamcorper placerat ipsum. Cras nibh.
  Morbi vel justo vitae lacus tincidunt ultrices. Lorem ipsum dolor
  sit amet, consectetuer adipiscing elit. In hac habitasse platea
  dictumst. Integer tempus convallis augue. Etiam facilisis. Nunc
  elementum fermentum wisi.}

\texttt{\textbf{align=ll}}

\cutbox[align=ll]{Quisque ullamcorper placerat ipsum. Cras nibh.
  Morbi vel justo vitae lacus tincidunt ultrices. Lorem ipsum dolor
  sit amet, consectetuer adipiscing elit. In hac habitasse platea
  dictumst. Integer tempus convallis augue. Etiam facilisis. Nunc
  elementum fermentum wisi.}

\texttt{\textbf{align=rl}}

\cutbox[align=rl]{Quisque ullamcorper placerat ipsum. Cras nibh.
  Morbi vel justo vitae lacus tincidunt ultrices. Lorem ipsum dolor
  sit amet, consectetuer adipiscing elit. In hac habitasse platea
  dictumst. Integer tempus convallis augue. Etiam facilisis. Nunc
  elementum fermentum wisi.}

\texttt{\textbf{align=lr}}

\cutbox[align=lr]{Quisque ullamcorper placerat ipsum. Cras nibh.
  Morbi vel justo vitae lacus tincidunt ultrices. Lorem ipsum dolor
  sit amet, consectetuer adipiscing elit. In hac habitasse platea
  dictumst. Integer tempus convallis augue. Etiam facilisis. Nunc
  elementum fermentum wisi.}

\end{document}
  • Wow. It is not the same meaning of "easy" as I am aware of... And it works fine. Is it possible to let it "ignore" the outer box dimensions? The text is about to "fit" in 47.5mm wide parbox frame but the cutwidth can be 55mm before it starts to colide with the logo. I have hacked the issue by negative hspace and adjusting the parbox width. – Crowley May 22 '18 at 16:34
  • @Crowley I don't realy get your question. This sounds like, if 47.5mm doesn't fit, try 55mm, if that doesn't fit either, go back to 47.5mm and break the line. Is that about right? – Mike May 22 '18 at 22:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.