%2C%20der%20in%20einem%20Makro%20enthalten%20ist.png)
Nehmen wir an, wir haben eine Menge Text, der in einem einzigen Makro gesetzt werden soll. Nennen wir es\myverylongtext
\newcommand{\myverylongtext}{
This is some really long text: \blindtext[4].
And it continues even more: \blindtext[1].
}
Der Einfachheit halber nehmen wir an, dass es in keinen Abschnitts-/Newpage-Befehl gibt \myverylongtext
, aber Zeilenumbruchbefehle und mehrere Absätze (Absatzumbruchbefehle?) enthalten können. Nehmen wir außerdem an, dass Schriftgröße und Zeilenabstand durchgehend konstant bleiben, obwohl alle anderen LaTeX-Satzbefehle (\textbf usw.) im Text zulässig sind und wirksam sein sollten.
Ist es möglich, ein effizientes* Makro zu definieren, das (wenn es gefunden wird) den nächsten Textblock der angegebenen Dimension abruft? Beispiel:
\newcommand{\getnextchunk}[4]{
% #1 is name of macro (in our case \myverylongtext)
% #2 width of text box
% #3 height of text box in lines
% #4 draftmode: optional boolean argument that, when set, instead of typesetting contents returns the actual height (in lines), and width (in length units) of the chunk. (useful in making dynamic layout decisions)
% returns/typesets a box of shape width * height
}
Neue Aufrufe dieses Makros \getnextchunk
sollten den nächsten Textblock abrufen, als ob der darin enthaltene Text \myverylongtext
vom vorherigen Block in diesen Block umgebrochen würde.
* Dies \myverylongtext
kann sehr lang sein, und es kann zahlreiche solcher Blöcke geben, daher ist Effizienz erforderlich. Sie können den verbleibenden Teil nicht \myverylongtext
mehrfach setzen. Eine meiner Lösungsvorstellungen für dieses Problem ist, dass eine Box der Größe 0 iterativ gefüllt wird, bis sie die angegebene Größe erreicht: Breite (in Längendimension), Höhe (in Zeilen) und erforderliche Ausrichtung; allerdings fehlen mir die Kenntnisse von Low-Level-Tex/Luatex/Expl3, um dies selbst zu schreiben.
Außerdem sollten entweder in angegebene Ausrichtungsbefehle wie „raggedright“/„raggedleft“/„full-justified“ wie \myverylongtext
durch Zauberhand wirksam werden, oder wir können eine Einschränkung festlegen, dass wir solche Befehle nicht in „ \myverylongtext
&“ haben, sondern sie stattdessen als viertes Argument an übergeben \getnextchunk
(ich denke, Letzteres ist vorzuziehen, und würde das Codieren/Verwenden entweder einfacher und/oder sauberer machen).
Eine andere Möglichkeit, sich das Problem vorzustellen, ist, sich vorzustellen, dass wir mehrere rechteckige Textfelder (mit unterschiedlicher Breite und Höhe) haben, die nacheinander ineinander übergehen, wenn wir sie in unserem Dokument antreffen (machen Sie sich keine Gedanken über die Platzierung dieser Textfelder, *tex hat dafür bereits mehrere elegante Lösungen). Außerdem wissen wir nicht im Voraus, wann und wie viele solcher Textfelder im Dokument vorkommen werden. Meiner Meinung nach, nach Jahren der Verwendung von *tex, wird die Lösung nur dieses einen Problems unzählige Möglichkeiten eröffnen und tex als typografisches Werkzeug für designorientierte Layouts unschlagbar machen (gegenüber InDesign usw.). Werkzeuge wie InDesign und Affinity Publisher ermöglichen das Verknüpfen von Textfeldern, die schließlich als Stream ineinander übergehen, und sind unverzichtbar für ein typografisches System, das moderne ausdrucksstarke Typografie und eine Vielzahl von Designs unterstützen soll. Das kann *tex als Schriftsetzer einer viel breiteren Satz-/Design-Community zugänglich machen.
Antwort1
Meine Lösung ist nicht ganz das, was Sie möchten, aber alle Informationen werden an einem Ort verwaltet. Ich hoffe, dass es kein Problem ist, drei Parameterübergaben zu akzeptieren.
Die Daten sollten folgendermaßen aussehen:
% lines width
\declchunk 5 10cm ;
\declchunk 6 12cm ;
\declchunk 12 13cm ;
\declchunk 9 10cm ;
\declchunk 9 10cm ;
\declchunk 9 10cm ;
\declchunk 7 8cm ;
\declchunk 5 10cm ;
\formatchunks \myverylongtext
\setbox101 = \getnextchunk
\setbox102 = \getnextchunk \rebox 102:{\raggedright}
\setbox103 = \getnextchunk
\setbox104 = \getnextchunk \rebox 104:{\raggedleft}
\setbox105 = \getnextchunk
% you can place these boxes everywhere. the following code is only for testing:
box 101: \par \box101 \bigskip
box 102: \par \box102 \bigskip
box 103: \par \box103 \bigskip
box 104: \par \box104 \bigskip
box 105: \par \box105 \bigskip
\bye
Zuerst verlangsamen wir die Dimensionen aller Blöcke (nach Zeilenanzahl für die Höhe und nach Dimensionen für die Breite). Dann formatieren wir den gegebenen Text. Schließlich können wir Teile der Daten abrufen und sie beispielsweise in Boxen speichern. Sie sind standardmäßig in Blöcken ausgerichtet. Wenn wir eine andere Einstellung vornehmen müssen, können wir diese Boxen neu einordnen. Unser Beispiel zeigt, dass die zweite Box rechts und die vierte Box links ausgerichtet ist. Außerdem können Sie Folgendes tun:
\vbox to<dimension>{\unvbox103} \vtop to12mm{\unvbox105} etc.
beispielsweise weil zwischen den Linien eine Dehnbarkeit und Schrumpfbarkeit besteht.
Implementierung: Wir holen alle \parshape
Parameter aus der Liste der \declchunk
s, dann formatieren wir den Text mit diesen Parametern (nur einmal) \vbox\allchunks
und dann führen wir dies aus, \vsplit
wenn \getnextcunk
aufgerufen wird. Schließlich können wir ein wenig neu verpacken, wenn der Benutzer eine etwas andere Formularblockausrichtung benötigt.
Meine Implementierung funktioniert nur mit einfachem TeX und klassischem TeX. Wir brauchen keine TeX-Erweiterung und (natürlich) brauchen wir kein LaTeX:).
\newcount\tmpnum
\newcount\shapenum
\newcount\globpar
\newbox\allchunks
\newif\ifrepeat
\splittopskip=\baselineskip
\def\formatchunks#1{\setbox\allchunks=\vbox{%
\def\par{\ifhmode\shapepar\fi}
\def\shapepar{\prevgraf=\globpar
\parshape\shapenum\shapelist \endgraf
\globpar=\prevgraf
\ifnum\prevgraf>\shapenum \let\par=\endgraf \fi}
\dimen0=\baselineskip \baselineskip=\dimen0 plus2pt minus2pt
\widowpenalty=0 \clubpenalty=0 \brokenpenalty=0
\penalty0 #1\vfil}
\setbox0=\vsplit\allchunks to0pt % \splittopskip added
\expandafter \renewsize \sizelist \relax
}
\def\shapelist{} \def\sizelist{}
\splittopskip=\baselineskip
\def\shapelist{} \def\sizelist{}
\def\declchunk #1 #2;{\edef\sizelist{\sizelist#1\space}
\tmpnum=0
\loop \advance\tmpnum by1 \advance\shapenum by1
\edef\shapelist{\shapelist 0pt#2}%
\ifnum\tmpnum<#1 \repeat
}
\def\getnextchunk{\vsplit\allchunks to\size
\ifx\sizelist\empty \def\size{\baselineskip}%
\else \expandafter \renewsize \sizelist \relax \fi
}
\def\renewsize #1 #2\relax{%
\def\size{#1\baselineskip}\def\sizelist{#2}%
}
\def\rebox#1:#2{\setbox#1=\vbox{%
\setbox0=\hbox{}%
\repeattrue
\def\raggedright{\rightskip=0pt plus1fill minus1em \relax}%
\def\raggedleft{\leftskip=0pt plus1fill minus1em \relax}%
\hsize=\wd#1
\unvbox#1
\loop
\setbox2=\lastbox
\ifvoid2 \repeatfalse
\else \setbox0=\hbox{\hbox{\unhbox2}\penalty-10000 \unhbox0 }
\unskip\unskip\unpenalty
\fi
\ifrepeat \repeat
\null
#2\noindent \hfil \unhbox0 \par
}}
\def\myverylongtext{%
Lorem ipsum dolor sit amet, consectetuer
...
purus eget enim. Nunc vitae tortor. Proin tempus nibh sit amet nisl.
Vivamus quis tortor vitae risus porta vehicula.
}