commit d497dde1e06809c6caa3b2bb4af647082bfa480a
Author: Juergen Spitzmueller <[email protected]>
Date:   Sun Aug 2 12:21:50 2026 +0200

    Add support for parfill(skip) (#12949)
    
    File format change
---
 development/FORMAT                  |   7 ++
 lib/doc/Customization.lyx           | 243 ++++++++++++++++++++++++++++++++++++
 lib/doc/de/Customization.lyx        | 181 +++++++++++++++++++++++++++
 lib/layouts/scrclass.inc            |   3 +
 lib/lyx2lyx/lyx_2_6.py              |  38 +++++-
 src/BufferParams.cpp                | 138 +++++++++++++++++++-
 src/BufferParams.h                  |  22 ++++
 src/TextClass.cpp                   |  19 +++
 src/TextClass.h                     |  12 ++
 src/frontends/qt/GuiDocument.cpp    |  49 ++++++++
 src/frontends/qt/GuiDocument.h      |   1 +
 src/frontends/qt/LengthCombo.cpp    |   5 +-
 src/frontends/qt/ui/TextLayoutUi.ui |  79 ++++++++++--
 src/support/Length.cpp              |   2 +
 src/support/Length.h                |   1 +
 src/support/lengthcommon.cpp        |   4 +-
 src/version.h                       |   4 +-
 17 files changed, 791 insertions(+), 17 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 0e9e95f012..21bad579ed 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -7,6 +7,13 @@ changes happened in particular if possible. A good example 
would be
 
 -----------------------
 
+2026-08-02 Jürgen Spitzmüller <[email protected]>
+       * Format incremented to 656: Support for parfillskip
+         New buffer param \parfillskip "<type>" "<glue length>"
+         where <type> is either of "default", "none", "thirdline",
+         "quarterline" or "custom", and <glue length> is only used
+         in the custom case (otherwise an empty string).
+
 2026-07-30 Koji Yokota <[email protected]>
        * Format incremented to 655:
          Support ARGB colors. \color now takes 32bit hexnames instead of 16bit
diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx
index 6d66f45aa2..c4e396b38f 100644
--- a/lib/doc/Customization.lyx
+++ b/lib/doc/Customization.lyx
@@ -12593,6 +12593,243 @@ parskip=half
 parskip
 \emph default
  package.
+\change_inserted -712698321 1785664297
+
+\end_layout
+
+\begin_layout Description
+
+\change_inserted -712698321 1785665160
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664317
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664297
+string
+\end_layout
+
+\end_inset
+
+] If the class has an option to set 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785665160
+parfillskip
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ to zero,
+ specify it here (e.g.,
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664387
+parfullskip=none
+\end_layout
+
+\end_inset
+
+).
+ This then outputs the option rather than using the 
+\emph on
+parskip
+\emph default
+ package.
+ If the option is combined with the parskip option (as in KOMA classes),
+ you can use the 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664524
+$$PSOPT
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ placeholder (e.g.,
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664534
+$$PSOPT-
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ in KOMA results in 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664542
+parskip=full-
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ together with 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664507
+ParskipFull parskip=full
+\end_layout
+
+\end_inset
+
+).
+\change_unchanged
+
+\end_layout
+
+\begin_layout Description
+
+\change_inserted -712698321 1785665172
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664326
+ParfillskipQuarter
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664297
+string
+\end_layout
+
+\end_inset
+
+] Similar than 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664574
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+,
+ but for 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785665172
+parfillskip
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ of a quarter of the line.
+\end_layout
+
+\begin_layout Description
+
+\change_inserted -712698321 1785665179
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664337
+ParfillskipThird
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664331
+string
+\end_layout
+
+\end_inset
+
+] Similar than 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785664602
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+,
+ but for 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1785665179
+parfillskip
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+ of a third of the line.
+\change_unchanged
+
 \end_layout
 
 \begin_layout Description
@@ -24355,6 +24592,8 @@ status collapsed
 
 \change_inserted -712698321 1783145646
 IsInherited
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -24369,6 +24608,8 @@ status collapsed
 
 \emph on
 0
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -24385,6 +24626,8 @@ status collapsed
 
 \change_inserted -712698321 1783145638
 1
+\change_unchanged
+
 \end_layout
 
 \end_inset
diff --git a/lib/doc/de/Customization.lyx b/lib/doc/de/Customization.lyx
index 748c8b27b2..5efed2f20e 100644
--- a/lib/doc/de/Customization.lyx
+++ b/lib/doc/de/Customization.lyx
@@ -11055,6 +11055,187 @@ parskip
  diese Option verwendet.
 \end_layout
 
+\begin_layout Description
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+string
+\end_layout
+
+\end_inset
+
+] Falls die Dokumentklasse eine Option zum Setzen des Werts von 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+parfillskip
+\end_layout
+
+\end_inset
+
+ auf Null,
+ geben Sie diese hier an (bspw.
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+parfullskip=none
+\end_layout
+
+\end_inset
+
+).
+ Dann wird statt des Pakets 
+\emph on
+parskip
+\emph default
+ diese Option verwendet.
+ Falls die Option mit der Parskip-Option kombiniert ist (wie in den 
KOMA-Klassen),
+ können Sie den Platzhalter 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+$$PSOPT
+\end_layout
+
+\end_inset
+
+ verwenden (bspw.
+ resultiert 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+$$PSOPT-
+\end_layout
+
+\end_inset
+
+ in KOMA zusammen 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParskipFull parskip=full
+\end_layout
+
+\end_inset
+
+ in 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+parskip=full-
+\end_layout
+
+\end_inset
+
+ ).
+\end_layout
+
+\begin_layout Description
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParfillskipQuarter
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+string
+\end_layout
+
+\end_inset
+
+] Ähnlich wie 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+,
+ aber für 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+parfillskip
+\end_layout
+
+\end_inset
+
+ mit einem Viertel der Zeile.
+\end_layout
+
+\begin_layout Description
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParfillskipThird
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+string
+\end_layout
+
+\end_inset
+
+] Ähnlich wie 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+ParfillskipNone
+\end_layout
+
+\end_inset
+
+,
+ aber für 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+parfillskip
+\end_layout
+
+\end_inset
+
+ mit einem Drittel der Zeile.
+\end_layout
+
 \begin_layout Standard
 Der Abschnitt 
 \begin_inset Flex Code
diff --git a/lib/layouts/scrclass.inc b/lib/layouts/scrclass.inc
index 6d989d390f..ff6f322347 100644
--- a/lib/layouts/scrclass.inc
+++ b/lib/layouts/scrclass.inc
@@ -23,6 +23,9 @@ ClassOptions
        PageSizeFormat       paper=$$s
        ParskipHalf          parskip=half
        ParskipFull          parskip=full
+       ParfillskipNone      $$PSOPT-
+       ParfillskipQuarter   $$PSOPT*
+       ParfillskipThird     $$PSOPT+
 End
 
 Style Standard
diff --git a/lib/lyx2lyx/lyx_2_6.py b/lib/lyx2lyx/lyx_2_6.py
index 68969a9191..5eed5cbe05 100644
--- a/lib/lyx2lyx/lyx_2_6.py
+++ b/lib/lyx2lyx/lyx_2_6.py
@@ -26,7 +26,6 @@ import unicodedata
 #    get_ert,
 #    hex2ratio,
 #    insert_to_preamble,
-#    latex_length,
 #    length_in_bp,
 #    lyx2latex,
 #    lyx2verbatim,
@@ -37,6 +36,7 @@ import unicodedata
 #    str2bool
 from lyx2lyx_tools import (
     add_to_preamble,
+    latex_length,
     put_cmd_in_ert
 )
 
@@ -1525,6 +1525,7 @@ def revert_mintedlangs(document):
             lps_res.append(l)
         document.body[k] = "lstparams \"%s\"" % ",".join(lps_res)
 
+
 def revert_hex32colors(document):
     """Revert 32bit ARGB hex colors to 16bit RGB"""
     i = 0
@@ -1568,6 +1569,37 @@ def revert_hex32colors(document):
         document.body[i] = "\\color %s" % ' '.join(hex16colors)
 
 
+def revert_parfillskip(document):
+    """Revert parfillskip setting to preamble code"""
+    i = find_token(document.header, "\\parfillskip", 0)
+    if i == -1:
+        return
+
+    # We need to use this regex since split() does not handle quote protection
+    parfillskip = [p for p in re.split("( |\\\".*?\\\"|'.*?')", 
document.header[i]) if p.strip()]
+    if len(parfillskip) == 0:
+        return
+
+    pfs_type = parfillskip[1].strip('"')
+    pfs_value = parfillskip[2].strip('"')
+    
+    del document.header[i]
+
+    if pfs_type == "default":
+        return
+    preamble = ""
+    if pfs_type == "none":
+        preamble = "\\setlength\\parfillskip{\\z@ plus 1fil}"
+    elif pfs_type == "thirdline":
+        preamble = "\\setlength\\parfillskip{.3333\\linewidth plus 1fil}"
+    elif pfs_type == "quarterline":
+        preamble = "\\setlength\\parfillskip{.25\\linewidth plus 1fil}"
+    elif pfs_type == "custom":
+        preamble = "\\setlength\\parfillskip{%s}" % latex_length(pfs_value)[1]
+
+    if preamble != "":
+        add_to_preamble(document, preamble)
+
 ##
 # Conversion hub
 #
@@ -1585,11 +1617,13 @@ convert = [
     [652, [convert_removed_numeric]],
     [653, []],
     [654, []],
-    [655, []]
+    [655, []],
+    [656, []]
 ]
 
 
 revert = [
+    [655, [revert_parfillskip]],
     [654, [revert_hex32colors]],
     [653, [revert_mintedlangs]],
     [652, [revert_specialfonts]],
diff --git a/src/BufferParams.cpp b/src/BufferParams.cpp
index 8714dddb4a..206a231481 100644
--- a/src/BufferParams.cpp
+++ b/src/BufferParams.cpp
@@ -75,6 +75,11 @@ static char const * const string_paragraph_separation[] = {
 };
 
 
+static char const * const string_parfill_skip[] = {
+       "default", "none", "thirdline", "quarterline", "custom", ""
+};
+
+
 static char const * const string_quotes_style[] = {
        "english", "swedish", "german", "polish", "swiss", "danish", "plain",
        "british", "swedishg", "french", "frenchin", "russian", "cjk", 
"cjkangle",
@@ -140,6 +145,30 @@ ParSepTranslator const & parseptranslator()
 }
 
 
+// ParfillsKIP
+typedef Translator<string, BufferParams::ParfillSkip> ParfillSkipTranslator;
+
+
+ParfillSkipTranslator const init_parfillskiptranslator()
+{
+       ParfillSkipTranslator translator
+               (string_parfill_skip[0], BufferParams::ParfillSkipDefault);
+       translator.addPair(string_parfill_skip[1], 
BufferParams::ParfillSkipNone);
+       translator.addPair(string_parfill_skip[2], 
BufferParams::ParfillSkipThirdLine);
+       translator.addPair(string_parfill_skip[3], 
BufferParams::ParfillSkipQuarterLine);
+       translator.addPair(string_parfill_skip[4], 
BufferParams::ParfillSkipCustom);
+       return translator;
+}
+
+
+ParfillSkipTranslator const & parfillskiptranslator()
+{
+       static ParfillSkipTranslator const translator =
+               init_parfillskiptranslator();
+       return translator;
+}
+
+
 // Quotes style
 typedef Translator<string, QuoteStyle> QuotesStyleTranslator;
 
@@ -353,6 +382,7 @@ public:
        IndicesList indiceslist;
        Spacing spacing;
        Length parindent;
+       GlueLength parfillskip;
        Length mathindent;
        /** This is the amount of space used for paragraph_separation "skip",
         * and for detached paragraphs in "indented" documents.
@@ -404,6 +434,7 @@ BufferParams::BufferParams()
        cite_engine_type_ = ENGINE_TYPE_DEFAULT;
        makeDocumentClass();
        paragraph_separation = ParagraphIndentSeparation;
+       parfill_skip = ParfillSkipDefault;
        is_math_indent = false;
        math_numbering_side = DEFAULT;
        quotes_style = QuoteStyle::English;
@@ -736,6 +767,41 @@ void BufferParams::setParIndent(Length const & indent)
 }
 
 
+GlueLength const & BufferParams::getParfillSkip() const
+{
+       return pimpl_->parfillskip;
+}
+
+
+string const BufferParams::getParfillSkipString() const
+{
+       string res;
+       switch (parfill_skip) {
+       case ParfillSkipDefault:
+               break;
+       case ParfillSkipNone:
+               res = "\\z@ plus 1fil";
+               break;
+       case ParfillSkipThirdLine:
+               res = ".3333\\linewidth plus 1fil";
+               break;
+       case ParfillSkipQuarterLine:
+               res = ".25\\linewidth plus 1fil";
+               break;
+       case ParfillSkipCustom:
+               res = getParfillSkip().asLatexString();
+               break;
+       }
+       return res;
+}
+
+
+void BufferParams::setParFillSkip(GlueLength const & skip)
+{
+       pimpl_->parfillskip = skip;
+}
+
+
 VSpace const & BufferParams::getDefSkip() const
 {
        return pimpl_->defskip;
@@ -1181,6 +1247,18 @@ string BufferParams::readToken(Lexer & lex, string const 
& token,
                                pimpl_->defskip = VSpace(VSpace::MEDSKIP);
                        break;
                }
+               if (token == "\\parfillskip") {
+                       string type;
+                       lex >> type;
+                       string val;
+                       lex >> val;
+                       parfill_skip = parfillskiptranslator().find(type);
+                       if (parfill_skip == ParfillSkipCustom)
+                               setParFillSkip(GlueLength(val));
+                       else
+                               setParFillSkip(GlueLength());
+                       break;
+               }
                if (token == "\\is_math_indent") {
                        lex >> is_math_indent;
                        break;
@@ -1993,6 +2071,7 @@ void BufferParams::writeFile(ostream & os, Buffer const * 
buf) const
                   << (getParIndent().empty() ? "default" : 
getParIndent().asString());
        else
                os << "\n\\defskip " << getDefSkip().asLyXCommand();
+       os << "\n\\parfillskip \"" << string_parfill_skip[parfill_skip] << "\" 
\"" << getParfillSkip().asString() << "\"";
        os << "\n\\is_math_indent " << is_math_indent;
        if (is_math_indent)
                os << "\n\\math_indentation "
@@ -2366,11 +2445,49 @@ bool BufferParams::writeLaTeX(otexstream & os, 
LaTeXFeatures & features,
                break;
        }
 
+       bool parfillskip_classopt = false;
        if (paragraph_separation) {
+               string psopt;
                if (!tclass.halfparskip().empty() && getDefSkip().kind() == 
VSpace::HALFLINE)
-                       clsoptions << tclass.halfparskip() << ",";
+                       psopt = tclass.halfparskip();
                if (!tclass.fullparskip().empty() && getDefSkip().kind() == 
VSpace::FULLLINE)
-                       clsoptions << tclass.fullparskip() << ",";
+                       psopt = tclass.fullparskip();
+               switch (parfill_skip) {
+               case ParfillSkipNone: {
+                       if (contains(tclass.noneparfillskip(), "$$PSOPT")) {
+                               psopt = subst(tclass.noneparfillskip(), 
"$$PSOPT", psopt);
+                               parfillskip_classopt = true;
+                       } else if (!tclass.noneparfillskip().empty()) {
+                               clsoptions << tclass.noneparfillskip() << ",";
+                               parfillskip_classopt = true;
+                       }
+                       break;
+               }
+               case ParfillSkipThirdLine: {
+                       if (contains(tclass.thirdparfillskip(), "$$PSOPT")) {
+                               psopt = subst(tclass.thirdparfillskip(), 
"$$PSOPT", psopt);
+                               parfillskip_classopt = true;
+                       } else if (!tclass.thirdparfillskip().empty()) {
+                               clsoptions << tclass.thirdparfillskip() << ",";
+                               parfillskip_classopt = true;
+                       }
+                       break;
+               }
+               case ParfillSkipQuarterLine: {
+                       if (contains(tclass.quarterparfillskip(), "$$PSOPT")) {
+                               psopt = subst(tclass.quarterparfillskip(), 
"$$PSOPT", psopt);
+                               parfillskip_classopt = true;
+                       } else if (!tclass.quarterparfillskip().empty()) {
+                               clsoptions << tclass.quarterparfillskip() << 
",";
+                               parfillskip_classopt = true;
+                       }
+                       break;
+               }
+               case ParfillSkipDefault:
+               case ParfillSkipCustom:
+                       break;
+               }
+               clsoptions << psopt << ",";
        }
 
        // language should be a parameter to \documentclass
@@ -2748,6 +2865,10 @@ bool BufferParams::writeLaTeX(otexstream & os, 
LaTeXFeatures & features,
                                // explicitly reset default (might have been 
changed
                                // in a class or package)
                                os << "\\parskip=.5\\baselineskip plus 
2pt\\relax\n";
+                       // parfillskip
+                       if (parfill_skip != ParfillSkipDefault)
+                               os << "\\setlength{\\parfillskip}{" << 
getParfillSkipString() << "}\n";
+
                } else if (!by_class_option) {
                        // load parskip package with required options
                        string psopts;
@@ -2758,6 +2879,16 @@ bool BufferParams::writeLaTeX(otexstream & os, 
LaTeXFeatures & features,
                                else
                                        psopts = "skip=" + psopt;
                        }
+                       string const parfill = getParfillSkipString();
+                       if (!parfill.empty()) {
+                               if (!psopts.empty())
+                                       psopts += ",";
+                               if (contains(parfill, ' '))
+                                       // glue length has spaces: embrace
+                                       psopts += "parfill={" + parfill + "}";
+                               else
+                                       psopts += "parfill=" + parfill;
+                       }
                        string const xpsopts = getPackageOptions("parskip");
                        if (!xpsopts.empty()) {
                                if (!psopts.empty())
@@ -2777,6 +2908,9 @@ bool BufferParams::writeLaTeX(otexstream & os, 
LaTeXFeatures & features,
                           << from_utf8(getParIndent().asLatexString())
                           << "}\n";
                }
+               // parfillskip
+               if (!parfillskip_classopt && parfill_skip != ParfillSkipDefault)
+                       os << "\\setlength{\\parfillskip}{" << 
getParfillSkipString() << "}\n";
        }
 
        if (is_math_indent) {
diff --git a/src/BufferParams.h b/src/BufferParams.h
index 1da3f1cdc7..5a1a67341a 100644
--- a/src/BufferParams.h
+++ b/src/BufferParams.h
@@ -45,6 +45,7 @@ class DocumentClass;
 class Encoding;
 class Font;
 class Format;
+class GlueLength;
 class IndicesList;
 class Language;
 class LaTeXFeatures;
@@ -75,6 +76,19 @@ public:
                ParagraphSkipSeparation
        };
        ///
+       enum ParfillSkip {
+               ///
+               ParfillSkipDefault,
+               ///
+               ParfillSkipNone,
+               ///
+               ParfillSkipThirdLine,
+               ///
+               ParfillSkipQuarterLine,
+               ///
+               ParfillSkipCustom
+       };
+       ///
        BufferParams();
 
        /// get l10n translated to the buffers language
@@ -111,6 +125,10 @@ public:
        VSpace const & getDefSkip() const;
        ///
        void setDefSkip(VSpace const & vs);
+       ///
+       GlueLength const & getParfillSkip() const;
+       ///
+       void setParFillSkip(GlueLength const & skip);
 
        ///
        Length const & getMathIndent() const;
@@ -137,6 +155,8 @@ public:
         */
        ParagraphSeparation paragraph_separation;
        ///
+       ParfillSkip parfill_skip;
+       ///
        QuoteStyle quotes_style;
        ///
        bool dynamic_quotes;
@@ -739,6 +759,8 @@ private:
        std::string const getBibtexCommand(std::string const & cmd,
                                           bool const warn) const;
        ///
+       std::string const getParfillSkipString() const;
+       ///
        DocumentClassPtr doc_class_;
        ///
        LayoutModuleList layout_modules_;
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 87c50d7546..38107c75ec 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -137,6 +137,7 @@ TextClass::TextClass()
          opt_pagesize_("default|a4|a5|b5|letter|legal|executive"),
          opt_pagestyle_("empty|plain|headings|fancy"), 
fontsize_format_("$$spt"), pagesize_("default"),
          pagesize_format_("$$spaper"), pagestyle_("default"), 
parskip_full_(""), parskip_half_(""),
+         parfillskip_none_(""), parfillskip_quarter_(""), 
parfillskip_third_(""),
          tablestyle_("default"), docbookroot_("article"), 
docbookforceabstract_(false),
          columns_(1), sides_(OneSide), secnumdepth_(3), tocdepth_(3), 
outputType_(LATEX),
          outputFormat_("latex"), has_output_format_(false), 
defaultfont_(sane_font), 
@@ -1091,6 +1092,9 @@ void TextClass::readClassOptions(Lexer & lexrc)
                CO_PAGESIZE,
                CO_PAGESIZE_FORMAT,
                CO_PAGESTYLE,
+               CO_PARFILLSKIP_NONE,
+               CO_PARFILLSKIP_QUARTER,
+               CO_PARFILLSKIP_THIRD,
                CO_PARSKIP_FULL,
                CO_PARSKIP_HALF,
                CO_OTHER,
@@ -1105,6 +1109,9 @@ void TextClass::readClassOptions(Lexer & lexrc)
                {"pagesize",  CO_PAGESIZE },
                {"pagesizeformat", CO_PAGESIZE_FORMAT },
                {"pagestyle", CO_PAGESTYLE },
+               {"parfillskipnone", CO_PARFILLSKIP_NONE },
+               {"parfillskipquarter", CO_PARFILLSKIP_QUARTER },
+               {"parfillskipthird", CO_PARFILLSKIP_THIRD },
                {"parskipfull", CO_PARSKIP_FULL },
                {"parskiphalf", CO_PARSKIP_HALF }
        };
@@ -1149,6 +1156,18 @@ void TextClass::readClassOptions(Lexer & lexrc)
                        lexrc.next();
                        parskip_half_ = rtrim(lexrc.getString());
                        break;
+               case CO_PARFILLSKIP_NONE:
+                       lexrc.next();
+                       parfillskip_none_ = rtrim(lexrc.getString());
+                       break;
+               case CO_PARFILLSKIP_QUARTER:
+                       lexrc.next();
+                       parfillskip_quarter_ = rtrim(lexrc.getString());
+                       break;
+               case CO_PARFILLSKIP_THIRD:
+                       lexrc.next();
+                       parfillskip_third_ = rtrim(lexrc.getString());
+                       break;
                case CO_OTHER:
                        lexrc.next();
                        if (options_.empty())
diff --git a/src/TextClass.h b/src/TextClass.h
index 9840a77237..f7673b10d8 100644
--- a/src/TextClass.h
+++ b/src/TextClass.h
@@ -292,6 +292,12 @@ protected:
        std::string parskip_full_;
        /// Option for half parskip
        std::string parskip_half_;
+       /// Option for zero parfillskip
+       std::string parfillskip_none_;
+       /// Option for 1/4 parfillskip
+       std::string parfillskip_quarter_;
+       /// Option for 1/3 parfillskip
+       std::string parfillskip_third_;
        ///
        std::string tablestyle_;
        ///
@@ -494,6 +500,12 @@ public:
        ///
        std::string const & halfparskip() const { return parskip_half_; }
        ///
+       std::string const & noneparfillskip() const { return parfillskip_none_; 
}
+       ///
+       std::string const & quarterparfillskip() const { return 
parfillskip_quarter_; }
+       ///
+       std::string const & thirdparfillskip() const { return 
parfillskip_third_; }
+       ///
        std::string const & pagestyle() const { return pagestyle_; }
        ///
        std::string const & tablestyle() const { return tablestyle_; }
diff --git a/src/frontends/qt/GuiDocument.cpp b/src/frontends/qt/GuiDocument.cpp
index aac142cbb2..eae5f727ca 100644
--- a/src/frontends/qt/GuiDocument.cpp
+++ b/src/frontends/qt/GuiDocument.cpp
@@ -885,6 +885,15 @@ GuiDocument::GuiDocument(GuiView & lv)
        connect(textLayoutModule->skipLengthCO, SIGNAL(activated(int)),
                this, SLOT(change_adaptor()));
 
+       connect(textLayoutModule->parfillskipCO, SIGNAL(activated(int)),
+               this, SLOT(setParfillSkip(int)));
+       connect(textLayoutModule->parfillskipCO, SIGNAL(activated(int)),
+               this, SLOT(change_adaptor()));
+       connect(textLayoutModule->parfillskipLE, SIGNAL(textChanged(const 
QString &)),
+               this, SLOT(change_adaptor()));
+       connect(textLayoutModule->parfillskipLengthCO, SIGNAL(activated(int)),
+               this, SLOT(change_adaptor()));
+
        connect(textLayoutModule->indentRB, SIGNAL(toggled(bool)),
                this, SLOT(enableIndent(bool)));
        connect(textLayoutModule->skipRB, SIGNAL(toggled(bool)),
@@ -918,6 +927,15 @@ GuiDocument::GuiDocument(GuiView & lv)
        textLayoutModule->skipCO->addItem(qt_("Medium Skip"), VSpace::MEDSKIP);
        textLayoutModule->skipCO->addItem(qt_("Big Skip"), VSpace::BIGSKIP);
        textLayoutModule->skipCO->addItem(qt_("Custom"), VSpace::LENGTH);
+
+       textLayoutModule->parfillskipCO->addItem(qt_("Default"), 
BufferParams::ParfillSkipDefault);
+       textLayoutModule->parfillskipCO->addItem(qt_("None[[Parfillskip]]"), 
BufferParams::ParfillSkipNone);
+       textLayoutModule->parfillskipCO->addItem(qt_("1/4 of Line"), 
BufferParams::ParfillSkipQuarterLine);
+       textLayoutModule->parfillskipCO->addItem(qt_("1/3 of Line"), 
BufferParams::ParfillSkipThirdLine);
+       textLayoutModule->parfillskipCO->addItem(qt_("Custom"), 
BufferParams::ParfillSkipCustom);
+       // parfillskip accepts glue length
+       
textLayoutModule->parfillskipLE->setValidator(glueLengthValidator(textLayoutModule->parfillskipLE));
+
        textLayoutModule->lspacingCO->insertItem(
                Spacing::Single, qt_("Single"));
        textLayoutModule->lspacingCO->insertItem(
@@ -931,6 +949,8 @@ GuiDocument::GuiDocument(GuiView & lv)
        bc().addCheckedLineEditPanel(textLayoutModule->indentLE, docPS, 
N_("Text Layout"));
        bc().addCheckedLineEdit(textLayoutModule->skipLE, 
textLayoutModule->skipRB);
        bc().addCheckedLineEditPanel(textLayoutModule->skipLE, docPS, N_("Text 
Layout"));
+       bc().addCheckedLineEdit(textLayoutModule->parfillskipLE, 
textLayoutModule->parfillskipLA);
+       bc().addCheckedLineEditPanel(textLayoutModule->parfillskipLE, docPS, 
N_("Text Layout"));
 
        textLayoutModule->tableStyleCO->addItem(qt_("Default"), 
toqstr("default"));
        getTableStyles();
@@ -2319,6 +2339,19 @@ void GuiDocument::setSkip(int item)
 }
 
 
+void GuiDocument::setParfillSkip(int item)
+{
+       BufferParams::ParfillSkip kind =
+               
BufferParams::ParfillSkip(textLayoutModule->parfillskipCO->itemData(item).toInt());
+       bool const enable = (kind == BufferParams::ParfillSkipCustom);
+       textLayoutModule->parfillskipLE->setEnabled(enable);
+       textLayoutModule->parfillskipLengthCO->setEnabled(enable);
+       // needed to catch empty custom case
+       bc().refresh();
+       isValid();
+}
+
+
 void GuiDocument::enableSkip(bool skip)
 {
        textLayoutModule->indentLE->setEnabled(!skip);
@@ -4426,6 +4459,16 @@ void GuiDocument::applyView()
                        break;
                }
        }
+       bp_.parfill_skip = 
BufferParams::ParfillSkip(textLayoutModule->parfillskipCO->itemData(
+                       
textLayoutModule->parfillskipCO->currentIndex()).toInt());
+       if (bp_.parfill_skip == BufferParams::ParfillSkipCustom) {
+               GlueLength 
parfillskip(widgetsToLength(textLayoutModule->parfillskipLE,
+                                                
textLayoutModule->parfillskipLengthCO));
+               bp_.setParFillSkip(parfillskip);
+       } else
+               // default
+               bp_.setParFillSkip(GlueLength());
+
        bp_.tablestyle = fromqstr(textLayoutModule->tableStyleCO->itemData(
                                      
textLayoutModule->tableStyleCO->currentIndex()).toString());
 
@@ -5062,6 +5105,12 @@ void GuiDocument::paramsToDialog()
                setSkip(textLayoutModule->skipCO->currentIndex());
        }
 
+       
textLayoutModule->parfillskipCO->setCurrentIndex(textLayoutModule->parfillskipCO->findData(bp_.parfill_skip));
+
+       lengthToWidgets(textLayoutModule->parfillskipLE,
+               textLayoutModule->parfillskipLengthCO,
+               bp_.getParfillSkip().asString(), default_unit);
+
        textLayoutModule->twoColumnCB->setChecked(
                bp_.columns == 2);
        
textLayoutModule->justCO->setCurrentIndex(textLayoutModule->justCO->findData(toqstr(bp_.justification)));
diff --git a/src/frontends/qt/GuiDocument.h b/src/frontends/qt/GuiDocument.h
index 41290a3a74..b5cc1cf05f 100644
--- a/src/frontends/qt/GuiDocument.h
+++ b/src/frontends/qt/GuiDocument.h
@@ -140,6 +140,7 @@ private Q_SLOTS:
        void enableIndent(bool);
        void setSkip(int);
        void enableSkip(bool);
+       void setParfillSkip(int);
        void allowMathIndent();
        void enableMathIndent(int);
        void browseLayout();
diff --git a/src/frontends/qt/LengthCombo.cpp b/src/frontends/qt/LengthCombo.cpp
index 1ab6d7df24..851e2fc286 100644
--- a/src/frontends/qt/LengthCombo.cpp
+++ b/src/frontends/qt/LengthCombo.cpp
@@ -28,9 +28,10 @@ LengthCombo::LengthCombo(QWidget * parent)
        : QComboBox(parent)
 {
        for (int i = 0; i < lyx::num_units; i++) {
-               // mu does not make sense usually
+               // mu and fil do not make sense usually
                // so it must be added manually, if needed
-               if (QLatin1String(lyx::unit_name[i]) == "mu")
+               if (QLatin1String(lyx::unit_name[i]) == "mu"
+                   || QLatin1String(lyx::unit_name[i]) == "fil")
                        continue;
                QComboBox::addItem(lyx::qt_(lyx::unit_name_gui[i]),
                        lyx::toqstr(lyx::unit_name[i]));
diff --git a/src/frontends/qt/ui/TextLayoutUi.ui 
b/src/frontends/qt/ui/TextLayoutUi.ui
index 3c2195a0b3..f9d92b25d2 100644
--- a/src/frontends/qt/ui/TextLayoutUi.ui
+++ b/src/frontends/qt/ui/TextLayoutUi.ui
@@ -6,14 +6,14 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>470</width>
-    <height>468</height>
+    <width>495</width>
+    <height>510</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string/>
   </property>
-  <layout class="QGridLayout" name="gridLayout_4">
+  <layout class="QGridLayout" name="gridLayout_5">
    <item row="0" column="0">
     <widget class="QGroupBox" name="separateGB">
      <property name="title">
@@ -198,6 +198,71 @@
     </widget>
    </item>
    <item row="1" column="0">
+    <widget class="QGroupBox" name="parfillGB">
+     <property name="title">
+      <string>Paragraph Fill</string>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_4">
+      <item row="0" column="0">
+       <widget class="QLabel" name="parfillskipLA">
+        <property name="text">
+         <string>Ma&amp;ximum last line fill:</string>
+        </property>
+        <property name="buddy">
+         <cstring>parfillskipCO</cstring>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="QComboBox" name="parfillskipCO">
+        <property name="toolTip">
+         <string>Specifiy the minimum amount of free space in the last line of 
a paragraph</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="2">
+       <widget class="QLineEdit" name="parfillskipLE">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="toolTip">
+         <string/>
+        </property>
+        <property name="inputMethodHints">
+         <set>Qt::ImhFormattedNumbersOnly</set>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="3">
+       <widget class="lyx::frontend::LengthCombo" name="parfillskipLengthCO">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
+        <property name="toolTip">
+         <string/>
+        </property>
+        <property name="inputMethodHints">
+         <set>Qt::ImhFormattedNumbersOnly|Qt::ImhLatinOnly</set>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="4">
+       <spacer name="spacer">
+        <property name="orientation">
+         <enum>Qt::Horizontal</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>2</width>
+          <height>20</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="0">
     <widget class="QGroupBox" name="spacingGB">
      <property name="minimumSize">
       <size>
@@ -270,7 +335,7 @@
      </layout>
     </widget>
    </item>
-   <item row="2" column="0">
+   <item row="3" column="0">
     <widget class="QGroupBox" name="tableStyleGB">
      <property name="title">
       <string>Table Style</string>
@@ -319,7 +384,7 @@
      </layout>
     </widget>
    </item>
-   <item row="3" column="0">
+   <item row="4" column="0">
     <widget class="QCheckBox" name="twoColumnCB">
      <property name="toolTip">
       <string>Format text into two columns</string>
@@ -329,7 +394,7 @@
      </property>
     </widget>
    </item>
-   <item row="4" column="0">
+   <item row="5" column="0">
     <layout class="QHBoxLayout" name="horizontalLayout_2">
      <item>
       <widget class="QLabel" name="justLA">
@@ -366,7 +431,7 @@
      </item>
     </layout>
    </item>
-   <item row="5" column="0">
+   <item row="6" column="0">
     <spacer>
      <property name="orientation">
       <enum>Qt::Vertical</enum>
diff --git a/src/support/Length.cpp b/src/support/Length.cpp
index f5c723f543..cdc0049e36 100644
--- a/src/support/Length.cpp
+++ b/src/support/Length.cpp
@@ -142,6 +142,7 @@ string const Length::asHTMLString() const
                os << formatFPNumber(val_) << '%';
                break;
        case SP:
+       case FIL:
        case UNIT_NONE:
                break;
        }
@@ -251,6 +252,7 @@ double Length::inInch(double text_width, double em_width, 
double margin) const
                // but we do not have this information here.
                result = val_ * em_width * 1.2 / 100;
                break;
+       case FIL:
        case Length::UNIT_NONE:
                result = 0;  // this cannot happen
                break;
diff --git a/src/support/Length.h b/src/support/Length.h
index 7863a9cfa5..865f61e791 100644
--- a/src/support/Length.h
+++ b/src/support/Length.h
@@ -44,6 +44,7 @@ public:
                DD, ///< Didot point = 1/72 of a French inch, = 0.376mm
                EM, ///< Width of capital "M" in current font.
                EX, ///< Height of a small "x" for the current font.
+               FIL, ///< Stretchable space, used as glue.
                IN, ///< Inch = 25.4mm = 72.27pt = 6.022pc
                MM, ///< Millimeter = 2.845pt
                MU, ///< Math unit (18mu = 1em) for positioning in math mode
diff --git a/src/support/lengthcommon.cpp b/src/support/lengthcommon.cpp
index 303dbcbc1f..f837f55c63 100644
--- a/src/support/lengthcommon.cpp
+++ b/src/support/lengthcommon.cpp
@@ -28,7 +28,7 @@ namespace lyx {
 
 // the latex units
 char const * const unit_name[] = {
-       "bp", "cc", "cm", "dd", "em", "ex", "in", "mm", "mu",
+       "bp", "cc", "cm", "dd", "em", "ex", "fil", "in", "mm", "mu",
        "pc", "pt", "sp",
        "text%",  "col%", "page%", "line%",
        "theight%", "pheight%", "baselineskip%", "" };
@@ -38,7 +38,7 @@ int const num_units = int(sizeof(unit_name) / 
sizeof(unit_name[0]) - 1);
 // the LyX gui units
 char const * const unit_name_gui[] = {
        N_("bp"), N_("cc[[unit of measure]]"), N_("cm"), N_("dd"), N_("em"),
-       N_("ex"), N_("in[[unit of measure]]"), N_("mm"), N_("mu[[unit of 
measure]]"), N_("pc"),
+       N_("ex"), N_("Elastic"), N_("in[[unit of measure]]"), N_("mm"), 
N_("mu[[unit of measure]]"), N_("pc"),
        N_("pt"), N_("sp"), N_("Text Width %"),
        N_("Column Width %"), N_("Page Width %"), N_("Line Width %"),
        N_("Text Height %"), N_("Page Height %"), N_("Line Distance %"), "" };
diff --git a/src/version.h b/src/version.h
index 8a494df25b..cd47b6268d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
 
 // Do not remove the comment below, so we get merge conflict in
 // independent branches. Instead add your own.
-#define LYX_FORMAT_LYX 655 // koji: ARGB colors
-#define LYX_FORMAT_TEX2LYX 655
+#define LYX_FORMAT_LYX 656 // spitz: parfillskip
+#define LYX_FORMAT_TEX2LYX 656
 
 #if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
 #ifndef _MSC_VER
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to