# Wrap text at any point if normal hyphenation not possible

I have data (generated from a database, not manually typed in) that mostly fits into a table cell with fixed width, but sometimes overflows because there are long words for which no hyphenation is found.

The problem can be demonstrated with the following example:

\documentclass{article}
\usepackage[utf8]{inputenc}
\begin{document}
\begin{tabular}{|p{1cm}|p{4cm}|}
1 & Cell where normal hyphenation is possible ÄÖÜ \\
\end{tabular}
\end{document}


My requirements are:

1. Text never overflows the cell (assuming some minimum width such that at least a handful characters have place)
2. First priority measure to achieve 1. is the normal hyphenation
3. If 2. fails, it is allowed to break the word at any character, so fill the line and break just before overflow would happen (disregarding normal hyphenation rules)

In the example, the overflow in cell 1 is prevented by measure 2., the normal hyphenation. The second cell overflows. I would like to have this cell treated by measure 3.

• Package seqsplit didn't help me
• The custom macro \wrap proposed in the answer to seqsplit - keep spaces comes near my wish, but can't handle the non-ascii characters ÄÖÜ (independent if they are input with utf8 input encoding or with \"A\"O\"U)
• As the text comes from a database, no manual editing of the cell content is wanted.

One of my ideas was to insert \linebreak[0] after every character, to tell LaTeX that a break can be made if no better opportunities exist. But this doesn't work like intended.

• I suspect you need to play with the penalties and glue. – John Kormylo Oct 14 '14 at 15:39

You can make a trial setting , see if you have any over large boxes, then if so loop through character by character adding \penalty0 and re-set.

\documentclass{article}
\usepackage[utf8]{inputenc}
\makeatletter
\def\foo#1{%
\setbox0\vbox{%
\global\let\foonext\foohyph
\hfuzz\maxdimen
#1\par
\loop
\unskip\unpenalty\unskip\unpenalty
\setbox\z@\lastbox
\ifvoid\z@
\else
\setbox\z@\hbox{\unhbox\z@}%
\ifdim\wd\z@>\dimexpr\hsize+4pt\relax% compensate for hfuzz and not checking for shrink
\global\let\foonext\foowrap
\fi
\repeat}%
\foonext{#1}%
}
\def\foohyph#1{#1}
\def\foowrap#1{\foowrap@#1\foowrap@}

\def\foowrap@{\futurelet\tmp\foowrap@@}

\def\foowrap@@{%
\let\next\relax
\ifx\tmp\foowrap@
\let\foowrap@\relax
\else\ifx\tmp\lbrace
\else\ifx\tmp\@sptoken
\let\next\foowrap@sp
\else\ifcat\noexpand\tmp\active% only active character utf8 chars
\let\next\foowrap@aa
\else
\let\next\foowrap@a
\fi\fi\fi\fi
\next
}

\def\foowrap@sp{\afterassignment\foowrap@\let\tmp= }

\def\foowrap@a#1{%
\leavevmode\penalty\z@#1\foowrap@}

\def\foowrap@aa#1#2{%
\leavevmode\penalty\z@#1#2%
\foowrap@}

\begin{document}
\begin{tabular}{|p{1cm}|p{4cm}|}
1 & \foo{Cell where normal hyphenation is possible ÄÖÜ}\\
\end{tabular}

\end{document}


This works when just two byte UTF-8 characters are used; testing three byte characters requires a more complex regular expression. Of course, with XeLaTeX or LuaLaTeX a simpler approach would be possible, because single letters would be seen.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{xparse,l3regex}

\newcommand{\breakandspace}{%
\nolinebreak % don't break here
\hspace{0pt plus 1fil}% add a filling space
\linebreak[0]% possible break here
\hspace{0pt plus -1fil}% remove the filling space
}

\ExplSyntaxOn
\NewDocumentCommand{\longcell}{m}
{
\mivt_long_cell:n { #1 }
}

\cs_new_protected:Npn \mivt_long_cell:n #1
{
\tl_set:Nn \l__mivt_cell_text_tl { #1 }
\regex_replace_all:nnN { (\cL.|\cA.{2}) } { \1\c{breakandspace} } \l__mivt_cell_text_tl
\tl_use:N \l__mivt_cell_text_tl
}
\ExplSyntaxOff

\begin{document}
\begin{tabular}{|p{1cm}|p{4cm}|}
1 & Cell where normal hyphenation is possible ÄÖÜ \\

The spaces will cancel with each other if the break is not taken at \linebreak[0]; if the break is taken, the second space will disappear at the left margin.
The regular expression search and replace will add \breakandspace after each letter or each group of two byte UTF-8 characters.