6

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 ÄÖÜ \\
2 & CellwherenormalhyphenationisnotpossiblebutshouldwrapinsteadofoverflowÄÖÜ
\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.

For the answer please consider:

  • 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.

Thanks for your suggestions!

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

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.

enter image description here

\documentclass{article}
\usepackage[utf8]{inputenc}
\makeatletter
\def\foo#1{%
\setbox0\vbox{%
\global\let\foonext\foohyph
\hbadness\maxdimen
\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 ÄÖÜ}\\
2 & \foo{CellwherenormalhyphenationisnotpossiblebutshouldwrapinsteadofoverflowÄÖÜ}
\end{tabular}




\end{document}
|improve this answer|||||
1

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 ÄÖÜ \\
2 & \longcell{CellwherenormalhyphenationisnotpossiblebutshouldwrapinsteadofoverflowÄÖÜ}
\end{tabular}
\end{document}

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.

enter image description here

The regular expression search and replace will add \breakandspace after each letter or each group of two byte UTF-8 characters.

|improve this answer|||||

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.