Sie sind hier

Vertikale Position der Kapitelüberschriften bei twocolumn

Hallo Markus,
beim Basteln meiner Wrapper-Klassen sind mir für den zweispaltigen Satz sind mir zwei Probleme aufgefallen, die allerdings auch bei den LaTeX-Standardklassen auftreten.

Zum einen wird der erste Absatz nach einer Kapitelüberschrift eingezogen. Ich habe keine Ahnung, ob das typographisch so gewollt und sinnvoll ist, allerdings ist dies bei einspaltigem Satz ja nicht der Fall. Zum anderen wird die Überschrift im zweispaltigen Satz höher gesetzt als beim einspaltigen. Das ist für mich persönlich insofern kritisch, als das bei meinem Layout sowohl der Titel, als auch die Überschriften für Teile und Kapitel zwingend auf der gleichen Höhe liegen müssen. Hältst du deinerseits eine Anpassung für KOMA-Script für notwendig? Falls ja, würde ich auf einen Bugfix von dir warten, ansonsten würde ich dies für meine Klassen selbst fixen.

Viele Grüße
Falk

\documentclass[twocolumn]{scrreprt}
\usepackage{blindtext}
\begin{document}
\chapter{Test}
\Blindtext[4]
\onecolumn
\chapter{Test}
\Blindtext[4]
\end{document}
Bild von Markus Kohm

Genau genommen handelt es sich dabei um ein Problem mit den Anweisungen \twocolumn und \onecolumn. Deren optionales Argument beachtet \topskip nicht. Ich habe vor Jahren einen ziemlich bescheuerten Hack dafür geschrieben, der manchmal funktioniert, manchmal leider auch nicht:

\makeatletter
\let\save@topnewpage\@topnewpage
\renewcommand{\@topnewpage}[1][]{%
  \save@topnewpage[{%
    \ifdim\parskip>\z@\null\fi
    \vskip\topskip\vskip\parskip\ignorespaces #1\par
    \ifdim\parskip>\z@\vskip\parskip\null\else\vskip\dp\strutbox\fi
    \aftergroup\@afterheading
  }]%
}
\makeatother

Falls jemand das optionale Argument von \twocolumn oder \onecolumn für etwas anderes verwendet als eine Überschrift, könnte das Ergebnis leicht anders ausfallen als erwartet. In dem Fall könnte vor allem das \aftergroup\@afterheading am Ende stören, das u. a. für das Wegfallen des Einzugs sorgt.

Ich habe obigen Code jedenfalls nie in KOMA-Script eingebaut, weil ich immer darauf hoffte, dass das Problem doch noch als Fehler anerkannt wird und zumindest in fixltx2e eine richtige Lösung dafür aufgenommen wird.

Aber vielleicht ist es ja langsam Zeit, das wenigstens optional anzubieten. Eventuell werde ich es in scrhack einbauen. Dort gibt es ohnehin bereits einen Mechanismus, um einzelne Hack zu deaktivieren. Versprechen will ich aber nichts.

Hallo Markus,

leider funktioniert dein Hack für die Position der Überschriften nur bei parskip=false. Außerdem stimmt der Abstand unterhalb der Überschrift und Text bei onecolumn und twocolumn unabhängig von parskip auch nicht überein. Hast du irgendetwas in petto?

Grüße
Falk

\documentclass[twocolumn,parskip=full]{scrreprt}
\usepackage{blindtext}
\makeatletter
\let\save@topnewpage\@topnewpage
\renewcommand{\@topnewpage}[1][]{%
  \save@topnewpage[{%
    \ifdim\parskip>\z@\null\fi
    \vskip\topskip\vskip\parskip\ignorespaces #1\par
    \ifdim\parskip>\z@\vskip\parskip\null\else\vskip\dp\strutbox\fi
    \aftergroup\@afterheading
  }]%
}
\makeatother
\begin{document}
\chapter{Test mithilfe eines Kapitels}
\Blindtext[3]
\onecolumn
\chapter{Test mithilfe eines Kapitels}
\Blindtext[3]
\end{document}
Bild von Markus Kohm

Der Hack behandelt die Verarbeitung des optionalen Arguments von \twocolumn. Er ist auf Deinen Fall also nur begrenzt anwendbar. Und nein, ich habe dafür keine Lösung parat. Man müsste dazu tiefer in Teile des LaTeX-Kernel-Codes einsteigen, in denen ich mich bisher nicht auskenne.

Wobei mir gerade auffällt, dass in Deinem Beispiel der Absatzabstand auf der ersten, zweispaltigen Seite ohnehin auseinander gezogen wird (underfull \vbox).

Dass der Code nicht funktioniert, liegt übrigens auch daran, dass im Beispiel innerhalb des einen \@topnewpage, das in Folge der ersten \chapter-Anweisung ausgeführt wird, \parskip tatsächlich Null ist – trotz Option parskip=full. Wie es scheint wird diese Option innerhalb des optionalen Arguments von \twocolumn überhaupt nicht richtig ausgewertet:

\documentclass[twocolumn,parskip=full]{scrreprt}
\usepackage{blindtext}
\begin{document}
\twocolumn[{Das: \Blindtext[2]}]
Versus: \Blindtext[2]
\end{document}

Das gilt übrigens auch für \parindent (wenn man beispielsweise um Beispiel die Option weg lässt).

Ich müsste jetzt also erst einmal dafür sorgen, dass \parskip etc. auch auf dieses Argument angewendet wird.

Aber irgendwo ist es auch nicht wirklich sinnvoll, dass ich blind daran herumstochere. Für eine richtige Lösung müsste ich wirklich die entsprechenden Teile des LaTeX-Kernels studieren, um die eigentliche Ursache des Problems anzugehen.

Dafür fehlt mir aber schlicht die Zeit (und ehrlich gesagt auch ein wenig die Lust).

Hallo Markus,

das Thema ist anscheinend schon altbekannt. Ich habe dazu einen passenden Eintrag in der LaTeX bugs database und die (fast) passende Lösung dazu gefunden. Diese hat es jedoch anscheinend nie in das fixltx2e-Paket geschafft. Ich habe mir den Vorschlag von Donald Arseneau (ohne die \showbox-Befehle, welche zu einem Fehler führen) genommen und -- Dank deiner ersten Lösung -- etwas angepasst. Ein erster Wurf sah so aus:

\documentclass[parskip=full]{scrreprt}
\usepackage{blindtext}
\makeatletter
\newlength{\save@parskip}
\long\def \@topnewpage [#1]{%
  \@nodocument
  \@next\@currbox\@freelist{}{}%
  \global \setbox\@currbox
    \vbox {%
      \break
      \prevdepth\z@
      \begingroup
      \setlength\save@parskip{\parskip}
      \normalcolor
      \hsize\textwidth
      \@parboxrestore
      \col@number \@ne
      \ifdim\save@parskip>\z@\null\fi
      \ignorespaces #1\par%
      \ifdim\save@parskip>\z@\null\fi
      \vskip -\dbltextfloatsep
      \endgroup%
      \null % ordinary \baselineskip
      \vskip -\topskip
  }%
  \begingroup 
%    \showbox\@currbox
    \splitmaxdepth\maxdepth \splittopskip\topskip
    \setbox\@tempboxa \vsplit\@currbox to\z@
  \endgroup
%  \showbox\@currbox
  \ifdim \ht\@currbox>\textheight
    \ht\@currbox \textheight
  \fi
  \global \count\@currbox \tw@
  \@tempdima -\ht\@currbox
  \advance \@tempdima -\dbltextfloatsep
  \global \advance \@colht \@tempdima
  \ifx \@dbltoplist \@empty
  \else
    \@latexerr{Float(s) lost}\@ehb
    \let \@dbltoplist \@empty
  \fi
  \@cons \@dbltoplist \@currbox
  \global \@dbltopnum \m@ne
  \ifdim \@colht<2.5\baselineskip
    \@latex@warning@no@line {Optional argument of \noexpand\twocolumn
                too tall on page \thepage}%
    \@emptycol
    \if@firstcolumn
    \else
      \@emptycol
    \fi
  \else
    \global \vsize \@colht
    \global \@colroom \@colht
    \@floatplacement
  \fi
}
\makeatother
\begin{document}
\chapter{Test}
\Blindtext[2]
\twocolumn
\chapter{Test}
%\noindent
\Blindtext[2]
\twocolumn[{Das: \Blindtext[2]}]
Versus: \Blindtext[2]
\end{document}

Soweit so gut, nur hatte die parskip-Einstellung immer noch keinen Einfluss auf das optionale Argument von \twocolumn. Der zweite Versuch passt eigentlich:

\documentclass[parskip=full]{scrreprt}
\usepackage{blindtext}
\makeatletter
\long\def \@topnewpage [#1]{%
  \@nodocument
  \@next\@currbox\@freelist{}{}%
  \global \setbox\@currbox
    \vbox {%
      \break
      \prevdepth\z@
      \begingroup
      \normalcolor
      \hsize\textwidth
%      \@parboxrestore
%      \KOMAoptions{parskip=current}
      \col@number \@ne
      \ignorespaces #1\par%
      \ifdim\parskip>\z@\null\fi
      \vskip -\dbltextfloatsep
      \endgroup%
      \null % ordinary \baselineskip
      \vskip -\topskip
  }%
  \begingroup 
%    \showbox\@currbox
    \splitmaxdepth\maxdepth \splittopskip\topskip
    \setbox\@tempboxa \vsplit\@currbox to\z@
  \endgroup
%  \showbox\@currbox
  \ifdim \ht\@currbox>\textheight
    \ht\@currbox \textheight
  \fi
  \global \count\@currbox \tw@
  \@tempdima -\ht\@currbox
  \advance \@tempdima -\dbltextfloatsep
  \global \advance \@colht \@tempdima
  \ifx \@dbltoplist \@empty
  \else
    \@latexerr{Float(s) lost}\@ehb
    \let \@dbltoplist \@empty
  \fi
  \@cons \@dbltoplist \@currbox
  \global \@dbltopnum \m@ne
  \ifdim \@colht<2.5\baselineskip
    \@latex@warning@no@line {Optional argument of \noexpand\twocolumn
                too tall on page \thepage}%
    \@emptycol
    \if@firstcolumn
    \else
      \@emptycol
    \fi
  \else
    \global \vsize \@colht
    \global \@colroom \@colht
    \@floatplacement
  \fi
}
\makeatother
\begin{document}
\chapter{Test}
\Blindtext[2]
\twocolumn
\chapter{Test}
%\noindent
\Blindtext[2]
\twocolumn[{Das: \Blindtext[2]}]
Versus: \Blindtext[2]
\end{document}

Ich bin mir nur nicht ganz schlüssig, ob ich einfach \@parboxrestore rausschmeißen kann, ohne mir später irgendwo Probleme einzuhandeln. Sollte der Befehl lieber erhalten bleiben, müsste man anschließend die aktuelle Einstellung für parksip erneut aufrufen. Leider gibt es bei KOMA-Script (noch) keine Option wie \KOMAoptions{parskip=current}. Diese wäre übrigens beispielsweise auch für die Verwendung von minipage-Umgebungen sehr wünschenswert.

Kannst du dir vorstellen, die Lösung in KOMA-Script einzubauen? Ich würde diese jedenfalls sehr gerne für meine eigenen Wrapper-Klassen nutzen und im Zweifelsfall selber implementieren.

Grüße
Falk

Bild von Markus Kohm

Bevor ich so etwas in KOMA-Script einbaue, müsste ich mir auch erst einmal die Zeit nehmen, den Original-Code und die Auswirkungen der Änderungen genauer anzuschauen. Das wird zumindest in der kommenden Version von KOMA-Script ganz sicher noch nicht der Fall sein.

Trotzdem danke dafür, dass Du das Ergebnis Deiner Recherchen hier angegeben hast. BTW: Du kannst ja noch einmal bei dem Bug-Report nachfragen, ob es eine Chance gibt, dass zumindest der dortige Fix in fixltx2e aufgenommen wird.

BTW: parskip=current würde nicht viel Sinn ergeben, wenn dann parskip=last (vgl. DIV=last).

...würde übrigens auch \setpartpreamble und \setchapterpreamble gut stehen. Diese beachten -- aufgrund der Verwendung von \parbox -- die Option parskip ebenfalls nicht.

Danke, hab's bei mir für die Kapitelüberschriften eingebaut.

Comments for "Vertikale Position der Kapitelüberschriften bei twocolumn" abonnieren