8

I'm looking for a way to obtain automatically the following layout of French "continuous guillemets", used in old typography when a citation includes another citation that spreads over several lines (ok, this might look strange at first sight):

« When Bill arrived at the door, he
saw him. The boy said: «Hello, I'm John
» and I'm 10 years old. I live
» with my parents in town. What
» do you want? » Bill was surprised
but answered the boy. »

I would like to do this automatically with XeLaTeX. The LaTeX code might look like this:

« When Bill arrived at the door, he saw him. The boy said: \continuousguil{Hello, I'm John and I'm 10 years old. I live with my parents in town. What do you want?} Bill was surprised but answered the boy. »

This is almost David's great answer in this post: Environment prints same character at beginning of each output line

But there are some differences, though, and I'm not able to adapt the code myself... Indeed, David's environment begins necessarily on a new line (whereas I want to begin in the middle of a line, possibly), and the same at the end: I'd like to be able to continue on the same line...

When I try to adapt the code, I am running into an error: "Improper \prevdepth".

Any idea on how to do this?

Thanks in advance!


Edit following David Carlisle's answer:

When trying your solution, I get something like this: example of nested citations

Two problems here: the first line of the nested citation is not justified, and there is some extra vertical space before the last line of the nested citation... This last problem does not always occur, though.

Just to be complete, I should mention that I replaced the "prefix" » in your code by \nospace{»}\hspace{.25em}, where the nospace command disables the automatic French spacing of the polyglossia package. Here is the complete code (I changed almost nothing to David's code; the \phantom{} at the beginning of the command is an ugly hack to have proper spacing after the guillemet):

\documentclass[12pt]{article} % Essai de guillemets continus

\usepackage{fontspec}
\defaultfontfeatures{Mapping=tex-text}
\setmainfont[Ligatures={TeX}, Numbers={OldStyle}]{Adobe Garamond Pro}

\usepackage{polyglossia}
\setdefaultlanguage{french}
\renewcommand\labelitemi{---}

\usepackage{microtype}

\setlength\textwidth{10cm}

% Enlever espace avant ponctuation
\makeatletter
\newcommand{\nospace}[1]{\nofrench@punctuation#1\french@punctuation}
\makeatother


% Commande guilcont

\makeatletter
%https://tex.stackexchange.com/questions/107726/how-to-get-the-natural-width-of-the-last-box-in-a-paragraph/107727#107727
\def\lastlinelength{%
{\abovedisplayshortskip\z@\abovedisplayskip\z@
    \belowdisplayshortskip\z@\belowdisplayskip\z@
$$\global\dimen\@ne\dimexpr\predisplaysize-2em\relax
 \xdef\tmp{%
      \predisplaysize\the\predisplaysize
      \prevgraf\the\prevgraf\relax}%
$$\vskip\dimexpr-\parskip-\baselineskip\relax}\tmp}


% The code for the start of  environment
\def\guilcont#1{«\phantom{}%
\lastlinelength
% save the depth of the previous line (Normally
% TeX uses this automatically but would lose the
% informatiom due to the boxing/reboxing)
\dimen0\prevdepth
% Save the prefix text from `#1` in box 0.
% In this version make it red, probably real code
% should not do that and should just have `#1` you
% could always add colour or font changes in the argument.
\setbox0\hbox{\nospace{»}\hspace{.25em}}%
% start saving the paragraph in box 2
\setbox2\vbox\bgroup\bgroup\vskip94sp
% by resetting the prevdepth to the saved value
% Tex will automatically insert glue to maintain even spacing
% before the first line.
\prevdepth\dimen0
% Reduce the width for line breaking by the width of box 0 to allow for
% the insertion of the prefix string later.
\advance\hsize-\wd0 
% end of begin environment code
\noindent\vadjust{\penalty123}\kern\dimen1 #1%
% close off the saving of box 2 started above.
\endgraf\egroup\egroup
% So at those point box 2 contains the body of the environment
% with lines broken to a short line length.
%
% Clear box 1 ready to start collecting the modified lines
\global\setbox1\vbox{}%
% Use unbox box2 (onto itself)
\setbox2\vbox{%
\unvbox2
\global\setbox5\lastbox
\unskip
% at this point we are at the end of box 2 now
% loop backwards up the vertical list copying glue and penalties
% but modifying boxes to add the prefix.
\loop
%
% an e-tex primitive that reports the last item in the vertical list.
% type 1 is a box, so remove the box (a line of text) and then
% put into box 1 a box that is this box together with the prefix which
% was saved in box 0
\ifnum\lastnodetype=1
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\copy0\box3}%
\unvbox1}%
\fi
%
% type 11 is glue so remove it from this list and add
% equivalent glue to box 1
\ifnum\lastnodetype=11
\skip0\lastskip\unskip
\global\setbox1\vbox{\vskip\skip0\unvbox1}%
\fi
%
% same for penalty
\ifnum\lastnodetype=13
\count0\lastpenalty\unpenalty
\ifnum\count0=123
\setbox0\hbox{}%
\else
\global\setbox1\vbox{\penalty\count0 \unvbox1}%
\fi
\fi
%
% other node types are not handled here: either they won't happen
% or they can't be removed anyway so would break the loop \special
% for example would be bad.
%
% -1 means the vertical list is empty: we have reached the top of the box.
\ifnum\lastnodetype=-1
\else
\repeat}%
% Tip the modified box back onto the main list for the page, unbox
% it so that page breaking may still happen (if it could happen in the
% original context).
\vskip-\baselineskip
\unvbox1
\noindent\nospace{»}\hspace{.25em}\unhbox5\unskip\unskip\ »%
}


\begin{document}

«Il y a huit ans que je suis avec vous, n'est-ce pas? Eh bien, dès le premier
jour, je me suis dit : \guilcont{Dès que j'aurai amassé cinq mille francs, je
  m'en retournerai là-bas; j'achèterai la maison à Lagache, et je vivrai bien
  heureuse…} C'est une promesse que je me suis faite, vous comprenez.»

\end{document}

Any idea on how I could fix these two minor problems? Thanks!

  • I have an answer, since I asked the same question in another forum a couple of years ago. I just have to find where I stored it on my computer. – Bernard Sep 20 '14 at 14:51
  • If you have to do this in a document written in French, the last version of babel-french provides a special command \frquote, with different options, that does what you wan automatically. I have never used it, though. – biozic Sep 22 '14 at 11:10
  • @biozic Ah, I didn't know that! Indeed, it is exactly what I wanted, thanks. However, I'm using polyglossia instead of babel, do you know if the same exists with polyglossia? And btw, what is the difference between babel and polyglossia: which one should I use preferably? – Sylvain Sep 22 '14 at 13:32
  • @Sylvain I have never used polyglossia, only tested it once, because it seems the options for the french language are scarce in polyglossia compared to what babel-french provides. – biozic Sep 23 '14 at 14:32
8

enter image description here

\documentclass{article}

\setlength\textwidth{3.5cm}
\usepackage[T1]{fontenc}% not for xetex
\usepackage[utf8]{inputenc}% not for xetex
\makeatletter
%http://tex.stackexchange.com/questions/107726/how-to-get-the-natural-width-of-the-last-box-in-a-paragraph/107727#107727
\def\lastlinelength{%
{\abovedisplayshortskip\z@\abovedisplayskip\z@
    \belowdisplayshortskip\z@\belowdisplayskip\z@
$$\global\dimen\@ne\dimexpr\predisplaysize-2em\relax
 \xdef\tmp{%
      \predisplaysize\the\predisplaysize
      \prevgraf\the\prevgraf\relax}%
$$\vskip\dimexpr-\parskip-\baselineskip\relax}\tmp}


% The code for the start of  environment
\def\continuousguil#1{ «%
\lastlinelength
% save the depth of the previous line (Normally
% TeX uses this automatically but would lose the
% informatiom due to the boxing/reboxing)
\dimen0\prevdepth
% Save the prefix text from `#1` in box 0.
% In this version make it red, probably real code
% should not do that and should just have `#1` you
% could always add colour or font changes in the argument.
\setbox0\hbox{» }%
% start saving the paragraph in box 2
\setbox2\vbox\bgroup\bgroup\vskip94sp
% by resetting the prevdepth to the saved value
% Tex will automatically insert glue to maintain even spacing
% before the first line.
\prevdepth\dimen0
% Reduce the width for line breaking by the width of box 0 to allow for
% the insertion of the prefix string later.
\advance\hsize-\wd0 
% end of begin environment code
\noindent\vadjust{\penalty123}\kern\dimen1 #1%
% close off the saving of box 2 started above.
\endgraf\egroup\egroup
% So at those point box 2 contains the body of the environment
% with lines broken to a short line length.
%
% Clear box 1 ready to start collecting the modified lines
\global\setbox1\vbox{}%
% Use unbox box2 (onto itself)
\setbox2\vbox{%
\unvbox2
\global\setbox5\lastbox
\unskip
% at this point we are at the end of box 2 now
% loop backwards up the vertical list copying glue and penalties
% but modifying boxes to add the prefix.
\loop
%
% an e-tex primitive that reports the last item in the vertical list.
% type 1 is a box, so remove the box (a line of text) and then
% put into box 1 a box that is this box together with the prefix which
% was saved in box 0
\ifnum\lastnodetype=1
\global\setbox3\lastbox
\global\setbox1\vbox{%
\hbox{\copy0\box3}%
\unvbox1}%
\fi
%
% type 11 is glue so remove it from this list and add
% equivalent glue to box 1
\ifnum\lastnodetype=11
\skip0\lastskip\unskip
\global\setbox1\vbox{\vskip\skip0\unvbox1}%
\fi
%
% same for penalty
\ifnum\lastnodetype=13
\count0\lastpenalty\unpenalty
\ifnum\count0=123
\setbox0\hbox{}%
\else
\global\setbox1\vbox{\penalty\count0 \unvbox1}%
\fi
\fi
%
% other node types are not handled here: either they won't happen
% or they can't be removed anyway so would break the loop \special
% for example would be bad.
%
% -1 means the vertical list is empty: we have reached the top of the box.
\ifnum\lastnodetype=-1
\else
\repeat}%
% Tip the modified box back onto the main list for the page, unbox
% it so that page breaking may still happen (if it could happen in the
% original context).
\vskip-\baselineskip
\unvbox1
\noindent » \unhbox5\unskip\unskip\ »
}


\begin{document}

\noindent
« When Bill arrived at the door, he saw him. The boy said:
\continuousguil{Hello, I'm John and I'm 10 years old. I live with my
  parents in town. What do you want?} Bill was surprised but answered
the boy. »

\end{document}
| improve this answer | |
  • you might want to alternate between single and double guillemets to indicate the level of discourse. also, i'd expect the "opening" form on the continuation lines. – barbara beeton Sep 20 '14 at 17:25
  • but @barbarabeeton, I always do what's requested, which was double here:-) (The guillemets appear in the code as literal text so can easily be changed, also I wasn't sure what the convention was for space before or after them) – David Carlisle Sep 20 '14 at 18:30
  • Thanks a lot David! Yes you used the right convention for spacing. – Sylvain Sep 21 '14 at 13:19
  • @barbarabeeton, actually we find both forms: "opening" or "closing" guillemets on the continuation lines... – Sylvain Sep 21 '14 at 14:06
  • @DavidCarlisle, now I'm trying your solution and run into small troubles. Sometimes there is too much vertical space before the last line of the nested citation. And the first line of it is not justified. I will edit my question to post an example. Thanks – Sylvain Sep 21 '14 at 14:13
3

There exists another approach which is simpler but with more compromises. The solution uses \discretionary to insert the desired text before each line.

\hsize=3.6cm
\emergencystretch=2em

\def\guilpar#1\par{\bgroup \frenchspacing \hyphenpenalty=10000
   \rightskip=-\fontdimen2\the\font plus-\fontdimen3\the\font minus-\fontdimen4\the\font
   \guilparA#1 {}
}
\def\guilparA #1 #2 {#1\ifx\end#2\end \guilparE\else \guilparB \expandafter\guilparA \fi #2 }
\def\guilparB{\nobreak\space\penalty0 }
\def\guilparC{\nobreak\space\discretionary{}{»\kern3pt}{}}
\def\guilparE{\par\egroup}

\def\continuousguil#1{%
   {\let\guilparE=\ignorespaces \let\guilparB=\guilparC \guilparA «#1~» {} }}

\guilpar \noindent
« When Bill arrived at door, he saw him. The boy said:
\continuousguil{Hello, I'm John and I'm 10 years old. I live with my
parents in   town. What do you want?} Bill was surprised but answered
the boy. »

\bye

The compromises are:

  • The \frenchspacing have to be used in the paragraph (but I hope that this is no real problem because this is intended to the French language).
  • The word hyphenation have to be turned off in such paragraph.

Description of the code: Each space in the paragraph signed by \guilpar is replaced by \nobreak\space\penalty0 -- the line beaking are done after space, no in space. The \rightskip includes the compensation of the last space on each line. Each space are replaced by \nobreak\space\discretionary in the \continuousguil argument.

| improve this answer | |
  • Thanks! That's a very clever idea - to use \discretionary. However, I get the error improper discretionary list when I run your example with the package polyglossia (and default language to French)... I don't know where it comes from (there is no error when I remove polyglossia). – Sylvain Sep 22 '14 at 10:57
  • @Sylvain IMHO, polyglossia gives to « more intelligence than the normal character. The replacing of \discretionary{}{»\kern3pt}{} by \discretionary{}{\hbox{»}\kern3pt}{} might help. – wipet Sep 22 '14 at 11:29
  • @Sylvain I've found that: if polyglossia is used then space glue is automatically inserted before » (maybe via \XeTeXcharclass, I didn't examine it in detail). The stretching/shrinking glue is denied in \discretionary argument. The \hbox{»} instead » helps. Maybe you need to remove the unwanted space by \hbox{\kern-3pt»} or something similar... – wipet Sep 22 '14 at 13:08

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.