commit e0aed404946348a161d825412cea1a3fcca05619
Author: Juergen Spitzmueller <[email protected]>
Date:   Tue Oct 21 06:20:19 2025 +0200

    Implement contextual text break via BreakCommand [Inset]Layout param
    
    This allows us to support \columnbreak in multicol module (#8718)
    and \framebreak in beamer
    
    A next step is probably to rename InsetNewpage to InsetTextbreak
    and LFUN_NEWPAGE_INSERT to LFUN_TEXTBREAK_INSERT, as newpage
    really is only one break that is supported
---
 development/FORMAT           |   5 ++
 lib/doc/Customization.lyx    | 172 +++++++++++++++++++++++++++++++++++++++++++
 lib/doc/de/Customization.lyx | 106 ++++++++++++++++++++++++++
 lib/layouts/beamer.layout    |   1 +
 lib/layouts/multicol.module  |   1 +
 lib/lyx2lyx/lyx_2_6.py       |  78 ++++++++++++++++++--
 lib/scripts/layout2layout.py |   8 +-
 lib/ui/stdcontext.inc        |   1 +
 lib/ui/stdmenus.inc          |   1 +
 po/lyx_pot.py                |   6 ++
 src/Layout.cpp               |  10 +++
 src/Layout.h                 |   6 ++
 src/LyXAction.cpp            |   2 +-
 src/Text.cpp                 |  38 ++++++++++
 src/Text.h                   |   2 +
 src/TextClass.cpp            |   2 +-
 src/factory.cpp              |   2 +
 src/frontends/qt/Menus.cpp   |  51 +++++++++++++
 src/insets/InsetLayout.cpp   |  10 +++
 src/insets/InsetLayout.h     |   6 ++
 src/insets/InsetNewpage.cpp  |  29 +++++++-
 src/insets/InsetNewpage.h    |  13 +++-
 src/version.h                |   4 +-
 23 files changed, 537 insertions(+), 17 deletions(-)

diff --git a/development/FORMAT b/development/FORMAT
index 1900f2fce4..8e7be9240f 100644
--- a/development/FORMAT
+++ b/development/FORMAT
@@ -7,6 +7,11 @@ changes happened in particular if possible. A good example 
would be
 
 -----------------------
 
+2025-10-21 Jürgen Spitzmüller <[email protected]>
+       * Format incremented to 646: Implement contextual text breaks
+         in Layout and InsetLayout:
+         BreakCommand <command> <GUI string>
+
 2025-10-10 Jürgen Spitzmüller <[email protected]>
        * Format incremented to 645: Support options and params
          in InsetMathRef. Syntax:
diff --git a/lib/doc/Customization.lyx b/lib/doc/Customization.lyx
index 4ac8be9bd8..dcadc71bcd 100644
--- a/lib/doc/Customization.lyx
+++ b/lib/doc/Customization.lyx
@@ -9775,6 +9775,8 @@ status collapsed
 
 \change_inserted -712698321 1759755035
 CrossrefNeedDef
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -9787,6 +9789,8 @@ status collapsed
 
 \change_inserted -712698321 1759755076
 cleveref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -9799,6 +9803,8 @@ status collapsed
 
 \change_inserted -712698321 1759755063
 prettyref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -9811,6 +9817,8 @@ status collapsed
 
 \change_inserted -712698321 1759755080
 refstyle
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -9823,6 +9831,8 @@ status collapsed
 
 \change_inserted -712698321 1759755092
 zref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -12814,6 +12824,73 @@ Note that a `float' here is a real number,
  If the next paragraph has another style,
  the separations are not simply added,
  but the maximum is taken.
+\change_inserted -712698321 1761019622
+
+\end_layout
+
+\begin_layout Description
+
+\change_inserted -712698321 1761019622
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019622
+BreakCommand
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019622
+<command>
+\end_layout
+
+\end_inset
+
+] [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019622
+<GUI string>
+\end_layout
+
+\end_inset
+
+] Defines a text break specific for this layout.
+ The command is given without preceding backslash (e.g.,
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019634
+BreakCommand framebreak 
+\begin_inset Quotes eld
+\end_inset
+
+Frame Break
+\begin_inset Quotes erd
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+).
+\change_unchanged
+
 \end_layout
 
 \begin_layout Description
@@ -18030,6 +18107,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 CrossrefNeedDef
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18042,6 +18121,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 cleveref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18054,6 +18135,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 prettyref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18066,6 +18149,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 refstyle
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18078,6 +18163,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 zref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18096,6 +18183,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 revert_ling_xrefs
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -18108,6 +18197,8 @@ status collapsed
 
 \change_inserted -712698321 1759755385
 lyx_2_6.py
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20004,6 +20095,73 @@ nolink "false"
 \end_inset
 
  for a list of the available color names.
+\change_inserted -712698321 1761019429
+
+\end_layout
+
+\begin_layout Description
+
+\change_inserted -712698321 1761019594
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019436
+BreakCommand
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019461
+<command>
+\end_layout
+
+\end_inset
+
+] [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019481
+<GUI string>
+\end_layout
+
+\end_inset
+
+] Defines a text break specific for this layout.
+ The command is given without preceding backslash (e.g.,
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+
+\change_inserted -712698321 1761019565
+BreakCommand columnbreak 
+\begin_inset Quotes eld
+\end_inset
+
+Column Break
+\begin_inset Quotes erd
+\end_inset
+
+
+\change_unchanged
+
+\end_layout
+
+\end_inset
+
+).
 \end_layout
 
 \begin_layout Description
@@ -20136,6 +20294,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 CrossrefNeedDef
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20148,6 +20308,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 cleveref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20160,6 +20322,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 prettyref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20172,6 +20336,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 refstyle
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20184,6 +20350,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 zref
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20202,6 +20370,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 revert_ling_xrefs
+\change_unchanged
+
 \end_layout
 
 \end_inset
@@ -20214,6 +20384,8 @@ status collapsed
 
 \change_inserted -712698321 1759755357
 lyx_2_6.py
+\change_unchanged
+
 \end_layout
 
 \end_inset
diff --git a/lib/doc/de/Customization.lyx b/lib/doc/de/Customization.lyx
index e0173b3fa0..5d369578c4 100644
--- a/lib/doc/de/Customization.lyx
+++ b/lib/doc/de/Customization.lyx
@@ -11328,6 +11328,59 @@ float
 \begin_inset Flex Code
 status collapsed
 
+\begin_layout Plain Layout
+BreakCommand
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+<Befehl>
+\end_layout
+
+\end_inset
+
+] [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+<GUI-String>
+\end_layout
+
+\end_inset
+
+] Definiert einen Textumbruch speziell für diesen Stil.
+ Der Befehl wird ohne voranstehenden Rückschrägstrich angegeben (bspw.
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+BreakCommand framebreak 
+\begin_inset Quotes eld
+\end_inset
+
+Frame Break
+\begin_inset Quotes erd
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Description
+\begin_inset Flex Code
+status collapsed
+
 \begin_layout Plain Layout
 Category
 \end_layout
@@ -18806,6 +18859,59 @@ nolink "false"
 \begin_inset Flex Code
 status collapsed
 
+\begin_layout Plain Layout
+BreakCommand
+\end_layout
+
+\end_inset
+
+ [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+<Befehl>
+\end_layout
+
+\end_inset
+
+] [
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+<GUI-String>
+\end_layout
+
+\end_inset
+
+] Definiert einen Textumbruch speziell für diesen Stil.
+ Der Befehl wird ohne voranstehenden Rückschrägstrich angegeben (bspw.
+ 
+\begin_inset Flex Code
+status collapsed
+
+\begin_layout Plain Layout
+BreakCommand columnbreak 
+\begin_inset Quotes eld
+\end_inset
+
+Column Break
+\begin_inset Quotes erd
+\end_inset
+
+
+\end_layout
+
+\end_inset
+
+).
+\end_layout
+
+\begin_layout Description
+\begin_inset Flex Code
+status collapsed
+
 \begin_layout Plain Layout
 ContentAsLabel
 \end_layout
diff --git a/lib/layouts/beamer.layout b/lib/layouts/beamer.layout
index f3dd5c6aad..c6c7e73c38 100644
--- a/lib/layouts/beamer.layout
+++ b/lib/layouts/beamer.layout
@@ -552,6 +552,7 @@ Style Frame
     AutoInsert     1
     IsTocCaption   1
   EndArgument
+  BreakCommand      framebreak "Frame Break"
   AutoNests 
        Standard,Itemize,Enumerate,Description,FrameTitle,FrameSubtitle,Column,
        
Columns,ColumnsCenterAligned,ColumnsTopAligned,Pause,Overprint,OverlayArea,Only,Block,
diff --git a/lib/layouts/multicol.module b/lib/layouts/multicol.module
index f29b682343..8ef1b5c456 100644
--- a/lib/layouts/multicol.module
+++ b/lib/layouts/multicol.module
@@ -38,6 +38,7 @@ InsetLayout Flex:Multiple_Columns
        DocBookTag      IGNORE
   EndArgument
   ResetsFont        true
+  BreakCommand      columnbreak "Column Break"
 
   # The current DocBook implementation is quite lacking, but it would require
   # a lot more C++ code to have perfect output. The major problem: not all
diff --git a/lib/lyx2lyx/lyx_2_6.py b/lib/lyx2lyx/lyx_2_6.py
index cc94ab147f..8b9d417712 100644
--- a/lib/lyx2lyx/lyx_2_6.py
+++ b/lib/lyx2lyx/lyx_2_6.py
@@ -28,14 +28,14 @@ import re
 #    length_in_bp,
 #    lyx2latex,
 #    lyx2verbatim,
-#    put_cmd_in_ert,
 #    revert_flex_inset,
 #    revert_flex_inset,
 #    revert_font_attrs,
 #    revert_language
 #    str2bool
 from lyx2lyx_tools import (
-    add_to_preamble
+    add_to_preamble,
+    put_cmd_in_ert
 )
 
 # Uncomment only what you need to import, please (parser_tools):
@@ -45,13 +45,9 @@ from lyx2lyx_tools import (
 #    del_value,
 #    find_complete_lines, 
 #    find_end_of,
-#    find_end_of_layout,
 #    find_substring,
-#    find_token_backwards,
 #    find_token_exact,
 #    find_tokens,
-#    get_containing_inset,
-#    get_containing_layout,
 #    get_bool_value,
 #    get_option_value,
 #    set_bool_value,
@@ -59,8 +55,13 @@ from lyx2lyx_tools import (
 from parser_tools import (
     del_token,
     find_end_of_inset,
+    find_end_of_layout,
+    find_end_of_sequence,
     find_re,
     find_token,
+    find_token_backwards,
+    get_containing_inset,
+    get_containing_layout,
     get_quoted_value,
     get_value
 )
@@ -571,6 +572,67 @@ def revert_mathref(document):
             ["\\usepackage{refstyle}"]
         )
 
+
+def revert_contextual_breaks(document):
+    "Revert contextual breaks in multicol and frame to LaTeX"
+
+    i = 0
+    while True:
+        i = find_token(document.body, "\\begin_inset Newpage contextual", i)
+        if i == -1:
+            break
+        j = find_end_of_inset(document.body, i)
+        if j == -1:
+            document.warning("Can't find end of Newpage inset at line %d!!" % 
(i))
+            i += 1
+            continue
+        # get the containing layout
+        lay = get_containing_layout(document.body, i)
+        if lay == False:
+            document.warning("No containing layout found!")
+            i += 1
+            continue
+        beglay = lay[1]
+        endlay = find_end_of_layout(document.body, beglay)
+        if endlay == False:
+            document.warning("Cannot find endlayout!")
+            i += 1
+            continue    
+        # check whether this is Frame
+        if lay[0] == "Frame":
+            document.body[i : j + 1] = put_cmd_in_ert("\\framebreak{}")
+            i += 1
+            continue
+        # next try inset
+        inInset = get_containing_inset(document.body, beglay)
+        if inInset and inInset[0] == "Flex Multiple Columns":
+            endInset = find_end_of_inset(document.body, inInset[1])
+            if endInset == -1:
+                 document.warning("Can't find end of multicol inset at line 
%d!!" % (inInset))
+                 i += 1
+                 continue
+            document.body[i : j + 1] = put_cmd_in_ert("\\columnbreak{}")
+            i += 1
+            continue
+        else:
+            # try layout
+            handled = False
+            k = i - 1
+            while True:
+                k = find_token_backwards(document.body, "\\begin_layout 
Frame", k)
+                if k == -1:
+                    break
+                l = find_end_of_sequence(document.body, k)
+                if l > i:
+                    document.body[i : j + 1] = put_cmd_in_ert("\\framebreak{}")
+                    i += 1
+                    handled = True
+                    break
+                k -= 1
+                continue
+            if not handled:
+                del document.body[beglay - 1 : endlay + 1]
+
 ##
 # Conversion hub
 #
@@ -578,11 +640,13 @@ def revert_mathref(document):
 supported_versions = ["2.6.0", "2.6"]
 convert = [
     [644, [convert_refname]],
-    [645, []]
+    [645, []],
+    [646, []]
 ]
 
 
 revert = [
+    [645, [revert_contextual_breaks]],
     [644, [revert_mathref]],
     [643, [revert_ling_xrefs]]
 ]
diff --git a/lib/scripts/layout2layout.py b/lib/scripts/layout2layout.py
index e8957db15b..fff8c41092 100644
--- a/lib/scripts/layout2layout.py
+++ b/lib/scripts/layout2layout.py
@@ -9,7 +9,7 @@
 # This script will update a .layout file to current format
 
 # The latest layout format is also defined in src/TextClass.cpp
-currentFormat = 112
+currentFormat = 113
 
 
 # Incremented to format 4, 6 April 2007, lasgouttes
@@ -381,6 +381,10 @@ currentFormat = 112
 # New InsetLayout tag "CrossrefNeedDef"
 # New Float tag "CrossrefNeedDef"
 
+# Incremented to format 113, 20 October 2025 by spitz
+# New Layout tag "BreakCommand"
+# New InsetLayout tag "BreakCommand"
+
 # Do not forget to document format change in Customization
 # Manual (section "Declaring a new text class").
 
@@ -720,7 +724,7 @@ def convert(lines, end_format):
                 i += 1
             continue
 
-        if 101 <= format <= 112:
+        if 101 <= format <= 113:
             # nothing to do.
             i += 1
             continue
diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc
index 316be4031b..a38e4f015b 100644
--- a/lib/ui/stdcontext.inc
+++ b/lib/ui/stdcontext.inc
@@ -350,6 +350,7 @@ Menuset
                Item "No Page Break|g" "inset-modify newpage nopagebreak"
                Item "Clear Page|C" "inset-modify newpage clearpage"
                Item "Clear Double Page|D" "inset-modify newpage 
cleardoublepage"
+               TextBreaksModify
        End
 
 #
diff --git a/lib/ui/stdmenus.inc b/lib/ui/stdmenus.inc
index 81df2b75a6..1ddaf4282e 100644
--- a/lib/ui/stdmenus.inc
+++ b/lib/ui/stdmenus.inc
@@ -474,6 +474,7 @@ Menuset
                Item "Prevent Page Break|g" "newpage-insert nopagebreak"
                Item "Clear Page|C" "newpage-insert clearpage"
                Item "Clear Double Page|D" "newpage-insert cleardoublepage"
+               TextBreaks
        End
 
        Menu "insert_math"
diff --git a/po/lyx_pot.py b/po/lyx_pot.py
index 9b07ef6abe..1a6d587b76 100755
--- a/po/lyx_pot.py
+++ b/po/lyx_pot.py
@@ -118,6 +118,7 @@ def layouts_l10n(input_files, output, base, 
layouttranslations):
     Comment = re.compile(r'^(.*)#')
     Translation = re.compile(r'^\s*Translation\s+(.*\S)\s*$', re.IGNORECASE)
     KeyValPair = re.compile(r'\s*"(.*)"\s+"(.*)"')
+    BreakCommand = re.compile(r'^\s*BreakCommand\s+(.*\S)\s+\"([^\"]*)\"', 
re.IGNORECASE)
 
     oldlanguages = []
     languages = []
@@ -394,6 +395,11 @@ def layouts_l10n(input_files, output, base, 
layouttranslations):
                         writeString(out, src, base, lineno, string)
                         writeString(out, src, base, lineno, string.lower())
                 continue
+            res = BreakCommand.search(line)
+            if res != None:
+                if not layouttranslations:
+                    writeString(out, src, base, lineno, res.group(2))
+                continue
             res = Float.search(line)
             if res != None:
                 readingFloat = True
diff --git a/src/Layout.cpp b/src/Layout.cpp
index 023fc04765..af04fa218d 100644
--- a/src/Layout.cpp
+++ b/src/Layout.cpp
@@ -42,6 +42,7 @@ enum LayoutTags {
        LT_AUTONESTEDBY,
        LT_MARGIN,
        LT_BOTTOMSEP,
+       LT_BREAKCOMMAND,
        LT_CATEGORY,
        LT_COMMANDDEPTH,
        LT_COPYSTYLE,
@@ -248,6 +249,7 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass 
const & tclass,
                { "autonests",      LT_AUTONESTS },
                { "babelpreamble",  LT_BABELPREAMBLE },
                { "bottomsep",      LT_BOTTOMSEP },
+               { "breakcommand",   LT_BREAKCOMMAND },
                { "category",       LT_CATEGORY },
                { "commanddepth",   LT_COMMANDDEPTH },
                { "copystyle",      LT_COPYSTYLE },
@@ -983,6 +985,14 @@ bool Layout::readIgnoreForcelocal(Lexer & lex, TextClass 
const & tclass,
                        lex >> is_toc_caption_;
                        break;
 
+               case LT_BREAKCOMMAND: {
+                       if (lex.next()) {
+                               string const cmd = lex.getString();
+                               string const gui = (lex.next()) ? 
lex.getString() : string();
+                               layout_break_ = make_pair(cmd, gui);
+                       }
+                       break;
+               }
                }
        }
        lex.popTable();
diff --git a/src/Layout.h b/src/Layout.h
index 9da3611a65..a1c25d0e3e 100644
--- a/src/Layout.h
+++ b/src/Layout.h
@@ -177,6 +177,10 @@ public:
        ///
        docstring rightdelim() const & { return rightdelim_; }
        ///
+       std::string const & breakCmd() const { return layout_break_.first; }
+       ///
+       std::string const & breakGUIName() const { return layout_break_.second; 
}
+       ///
        std::string const & innertag() const { return innertag_; }
        ///
        std::string const & labeltag() const { return labeltag_; }
@@ -698,6 +702,8 @@ private:
        std::string toc_type_;
        ///
        bool is_toc_caption_;
+       ///
+       std::pair<std::string, std::string> layout_break_;
 };
 
 
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index ecc7b4f327..d93df8cd44 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -3214,7 +3214,7 @@ void LyXAction::init()
  * \var lyx::FuncCode lyx::LFUN_NEWPAGE_INSERT
  * \li Action: Inserts a new page.
  * \li Syntax: newpage-insert <ARG>
- * \li Params: <ARG>: <newpage|pagebreak|clearpage|cleardoublepage> default: 
newpage
+ * \li Params: <ARG>: <newpage|pagebreak|clearpage|cleardoublepage|contextual> 
default: newpage
  * \li Origin: uwestoehr, 24 Nov 2007
  * \endvar
  */
diff --git a/src/Text.cpp b/src/Text.cpp
index 279285f425..f6223f39fb 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -6936,6 +6936,12 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & 
cmd,
                enable = !inDescriptionItem(cur)
                        && (cur.text()->getTocLevel(cur.pit()) == 
Layout::NOT_IN_TOC
                            || cur.pos() == 0 || cur.pos() == cur.lastpos());
+               if (cmd.getArg(0) == "contextual") {
+                       string cmd;
+                       string gui;
+                       getContextualBreak(paragraphs(), cur.pit(), cmd, gui);
+                       enable &= !cmd.empty();
+               }
                break;
 
        case LFUN_LANGUAGE:
@@ -7185,6 +7191,38 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & 
cmd,
 }
 
 
+void Text::getContextualBreak(ParagraphList const & pars, pit_type const & 
pit, string & cmd, string & gui) const
+{
+       cmd.clear();
+       gui.clear();
+       Paragraph const & par = pars.at(pit);
+       if (!par.layout().breakCmd().empty()) {
+               cmd = par.layout().breakCmd();
+               gui = par.layout().breakGUIName();
+               return;
+       }
+       pit_type prev_pit = pit - 1;
+       depth_type depth = par.getDepth();
+       while (prev_pit >= 0 && depth > 0) {
+               Paragraph const & prev_par = pars.at(prev_pit);
+               depth = prev_par.getDepth();
+               Layout const & layout = prev_par.layout();
+               if (!layout.breakCmd().empty()) {
+                       cmd = layout.breakCmd();
+                       gui = layout.breakGUIName();
+                       return;
+               }
+               --prev_pit;
+       }
+       InsetLayout const & il = par.inInset().getLayout();
+       if (!il.breakCmd().empty()) {
+               cmd = il.breakCmd();
+               gui = il.breakGUIName();
+               return;
+       }
+}
+
+
 void Text::pasteString(Cursor & cur, docstring const & clip,
                bool asParagraphs)
 {
diff --git a/src/Text.h b/src/Text.h
index 834e478b57..78da133ada 100644
--- a/src/Text.h
+++ b/src/Text.h
@@ -359,6 +359,8 @@ public:
        Font const outerFont(pit_type pit_offset) const;
        /// Return the label type at the end of paragraph \c pit.
        int getEndLabel(pit_type pit) const;
+       /// Get command and GUI string of contextual text breaks
+       void getContextualBreak(ParagraphList const & pars, pit_type const & 
pit, std::string & cmd, std::string & gui) const;
 
 private:
        /// The InsetText owner shall have access to everything.
diff --git a/src/TextClass.cpp b/src/TextClass.cpp
index 86760c2319..d5b63afa21 100644
--- a/src/TextClass.cpp
+++ b/src/TextClass.cpp
@@ -59,7 +59,7 @@ namespace lyx {
 // You should also run the development/tools/updatelayouts.py script,
 // to update the format of all of our layout files.
 //
-int const LAYOUT_FORMAT = 112; // spitz: CrossrefNeedDef tag
+int const LAYOUT_FORMAT = 113; // spitz: BreakCommand tag
 
 
 // Layout format for the current lyx file format. Controls which format is
diff --git a/src/factory.cpp b/src/factory.cpp
index c1477806f9..fc36228bbc 100644
--- a/src/factory.cpp
+++ b/src/factory.cpp
@@ -97,6 +97,8 @@ Inset * createInsetHelper(Buffer * buf, FuncRequest const & 
cmd)
                                inp.kind = InsetNewpageParams::CLEARDOUBLEPAGE;
                        else if (name == "nopagebreak")
                                inp.kind = InsetNewpageParams::NOPAGEBREAK;
+                       else if (name == "contextual")
+                               inp.kind = InsetNewpageParams::CONTEXTUAL;
                        return new InsetNewpage(inp);
                }
 
diff --git a/src/frontends/qt/Menus.cpp b/src/frontends/qt/Menus.cpp
index b89ffa233b..ce3c73faae 100644
--- a/src/frontends/qt/Menus.cpp
+++ b/src/frontends/qt/Menus.cpp
@@ -155,6 +155,10 @@ public:
                /** This is the list of selections that can
                    be pasted. */
                PasteRecent,
+               /** contextual text breaks */
+               TextBreaks,
+               /** modify contextual text breaks */
+               TextBreaksModify,
                /** toolbars */
                Toolbars,
                /** Available branches in document */
@@ -375,6 +379,7 @@ public:
        void expandToc2(Toc const & toc_list, size_t from, size_t to, int 
depth, const string & toc_type);
        void expandToc(Buffer const * buf);
        void expandPasteRecent(Buffer const * buf);
+       void expandTextBreaks(BufferView const * bv, bool modify = false);
        void expandToolbars();
        void expandBranches(Buffer const * buf);
        void expandIndices(Buffer const * buf, bool listof = false);
@@ -505,6 +510,8 @@ void MenuDefinition::read(Lexer & lex)
                md_env_separators,
                md_env_separatorscontext,
                md_switchquotes,
+               md_textbreaks,
+               md_textbreaksmodify,
                md_zoomoptions
        };
 
@@ -543,6 +550,8 @@ void MenuDefinition::read(Lexer & lex)
                { "switcharguments", md_switcharguments },
                { "switchcaptions", md_switchcaptions },
                { "switchquotes", md_switchquotes },
+               { "textbreaks", md_textbreaks },
+               { "textbreaksmodify", md_textbreaksmodify },
                { "toc", md_toc },
                { "toolbars", md_toolbars },
                { "updateformats", md_updateformats },
@@ -704,6 +713,15 @@ void MenuDefinition::read(Lexer & lex)
                        add(MenuItem(MenuItem::SwitchQuotes));
                        break;
 
+               case md_textbreaks:
+                       add(MenuItem(MenuItem::TextBreaks));
+                       break;
+
+               case md_textbreaksmodify:
+                       add(MenuItem(MenuItem::TextBreaksModify));
+                       break;
+               
+
                case md_zoomoptions:
                        add(MenuItem(MenuItem::ZoomOptions));
                        break;
@@ -1516,6 +1534,31 @@ void MenuDefinition::expandPasteRecent(Buffer const * 
buf)
 }
 
 
+void MenuDefinition::expandTextBreaks(BufferView const * bv, bool const modify)
+{
+       if (!bv)
+               return;
+       Text const * text = bv->cursor().text();
+       if (!text)
+               return;
+
+       string cmd;
+       string gui;
+       text->getContextualBreak(text->paragraphs(), bv->cursor().pit(), cmd, 
gui);
+       if (cmd.empty())
+               return;
+       if (gui.empty())
+               gui = to_utf8(_("Contextual Break"));
+       if (modify)
+               addWithStatusCheck(MenuItem(MenuItem::Command, qt_(gui),
+                                   FuncRequest(LFUN_INSET_MODIFY, "newpage 
contextual")));
+       else
+               add(MenuItem(MenuItem::Command, qt_(gui),
+                           FuncRequest(LFUN_NEWPAGE_INSERT, "contextual")));
+       
+}
+
+
 void MenuDefinition::expandToolbars()
 {
        MenuDefinition other_lists;
@@ -2497,6 +2540,14 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        tomenu.expandPasteRecent(buf);
                        break;
 
+               case MenuItem::TextBreaks:
+                       tomenu.expandTextBreaks(bv);
+                       break;
+
+               case MenuItem::TextBreaksModify:
+                       tomenu.expandTextBreaks(bv, true);
+                       break;
+
                case MenuItem::Toolbars:
                        tomenu.expandToolbars();
                        break;
diff --git a/src/insets/InsetLayout.cpp b/src/insets/InsetLayout.cpp
index c52fdc0a14..2b6ba3a6e4 100644
--- a/src/insets/InsetLayout.cpp
+++ b/src/insets/InsetLayout.cpp
@@ -77,6 +77,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & tclass,
                IL_ARGUMENT,
                IL_BABELPREAMBLE,
                IL_BGCOLOR,
+               IL_BREAKCOMMAND,
                IL_CONTENTASLABEL,
                IL_COPYSTYLE,
                IL_COUNTER,
@@ -171,6 +172,7 @@ bool InsetLayout::read(Lexer & lex, TextClass const & 
tclass,
                { "argument", IL_ARGUMENT },
                { "babelpreamble", IL_BABELPREAMBLE },
                { "bgcolor", IL_BGCOLOR },
+               { "breakcommand", IL_BREAKCOMMAND },
                { "contentaslabel", IL_CONTENTASLABEL },
                { "copystyle", IL_COPYSTYLE },
                { "counter", IL_COUNTER},
@@ -706,6 +708,14 @@ bool InsetLayout::read(Lexer & lex, TextClass const & 
tclass,
                case IL_STEPPARENTCOUNTER:
                        lex >> stepparentcounter_;
                        break;
+               case IL_BREAKCOMMAND: {
+                       if (lex.next()) {
+                               string const cmd = lex.getString();
+                               string const gui = (lex.next()) ? 
lex.getString() : string();
+                               layout_break_ = make_pair(cmd, gui);
+                       }
+                       break;
+               }
                case IL_END:
                        getout = true;
                        break;
diff --git a/src/insets/InsetLayout.h b/src/insets/InsetLayout.h
index b3f5aee5d0..1f4c29dc51 100644
--- a/src/insets/InsetLayout.h
+++ b/src/insets/InsetLayout.h
@@ -86,6 +86,10 @@ public:
        ///
        docstring const & rightdelim() const { return rightdelim_; }
        ///
+       std::string const & breakCmd() const { return layout_break_.first; }
+       ///
+       std::string const & breakGUIName() const { return layout_break_.second; 
}
+       ///
        bool inheritFont() const { return inheritfont_; }
        ///
        FontInfo const & font() const { return font_; }
@@ -479,6 +483,8 @@ private:
        bool insert_cotext_ = false;
        /// Step parent counter?
        bool stepparentcounter_ = false;
+       ///
+       std::pair<std::string, std::string> layout_break_;
 };
 
 ///
diff --git a/src/insets/InsetNewpage.cpp b/src/insets/InsetNewpage.cpp
index 4c7844374d..42db2ddbbe 100644
--- a/src/insets/InsetNewpage.cpp
+++ b/src/insets/InsetNewpage.cpp
@@ -13,10 +13,14 @@
 
 #include "InsetNewpage.h"
 
+#include "Buffer.h"
 #include "Cursor.h"
 #include "FuncRequest.h"
 #include "FuncStatus.h"
 #include "MetricsInfo.h"
+#include "Paragraph.h"
+#include "ParIterator.h"
+#include "Text.h"
 #include "xml.h"
 #include "texstream.h"
 #include "TextMetrics.h"
@@ -63,6 +67,9 @@ void InsetNewpageParams::write(ostream & os) const
        case InsetNewpageParams::NOPAGEBREAK:
                os <<  "nopagebreak";
                break;
+       case InsetNewpageParams::CONTEXTUAL:
+               os <<  "contextual";
+               break;
        }
 }
 
@@ -83,6 +90,8 @@ void InsetNewpageParams::read(Lexer & lex)
                kind = InsetNewpageParams::CLEARDOUBLEPAGE;
        else if (token == "nopagebreak")
                kind = InsetNewpageParams::NOPAGEBREAK;
+       else if (token == "contextual")
+               kind = InsetNewpageParams::CONTEXTUAL;
        else
                lex.printError("Unknown kind");
 }
@@ -218,14 +227,17 @@ bool InsetNewpage::getStatus(Cursor & cur, FuncRequest 
const & cmd,
 {
        switch (cmd.action()) {
        // we handle these
-       case LFUN_INSET_MODIFY:
+       case LFUN_INSET_MODIFY: {
+               bool enabled = true;
                if (cmd.getArg(0) == "newpage") {
                        InsetNewpageParams params;
                        string2params(to_utf8(cmd.argument()), params);
                        status.setOnOff(params_.kind == params.kind);
+                       enabled = params.kind != InsetNewpageParams::CONTEXTUAL 
|| !contextual_cmd_.empty();
                }
-               status.setEnabled(true);
+               status.setEnabled(enabled);
                return true;
+       }
        default:
                return Inset::getStatus(cur, cmd, status);
        }
@@ -245,6 +257,8 @@ docstring InsetNewpage::insetLabel() const
                        return _("Clear Double Page");
                case InsetNewpageParams::NOPAGEBREAK:
                        return _("No Page Break");
+               case InsetNewpageParams::CONTEXTUAL:
+                       return contextual_gui_.empty() ? _("Non-sensical 
Break") : _(contextual_gui_);
                default:
                        return _("New Page");
        }
@@ -260,6 +274,7 @@ ColorCode InsetNewpage::ColorName() const
                case InsetNewpageParams::NEWPAGE:
                case InsetNewpageParams::CLEARPAGE:
                case InsetNewpageParams::CLEARDOUBLEPAGE:
+               case InsetNewpageParams::CONTEXTUAL:
                        return Color_newpage;
        }
        // not really useful, but to avoids gcc complaints
@@ -291,6 +306,10 @@ void InsetNewpage::latex(otexstream & os, OutputParams 
const & runparams) const
                case InsetNewpageParams::NOPAGEBREAK:
                        os << "\\nopagebreak" << termcmd;
                        break;
+               case InsetNewpageParams::CONTEXTUAL:
+                       if (!contextual_cmd_.empty())
+                               os << "\\" << contextual_cmd_ << termcmd;
+                       break;
                default:
                        os << "\\newpage" << termcmd;
                        break;
@@ -324,6 +343,12 @@ docstring InsetNewpage::xhtml(XMLStream & xs, OutputParams 
const &) const
 }
 
 
+void InsetNewpage::updateBuffer(ParIterator const & it, UpdateType /* utype*/, 
bool const /*deleted*/)
+{
+       buffer().text().getContextualBreak(it.plist(), it.pit(), 
contextual_cmd_, contextual_gui_);
+}
+
+
 string InsetNewpage::contextMenuName() const
 {
        return "context-newpage";
diff --git a/src/insets/InsetNewpage.h b/src/insets/InsetNewpage.h
index 80fee2ffc9..1596c03009 100644
--- a/src/insets/InsetNewpage.h
+++ b/src/insets/InsetNewpage.h
@@ -20,7 +20,7 @@ namespace lyx {
 class InsetNewpageParams
 {
 public:
-       /// The different kinds of spaces we support
+       /// The different kinds of breaks we support
        enum Kind {
                ///
                NEWPAGE,
@@ -31,7 +31,9 @@ public:
                ///
                CLEARDOUBLEPAGE,
                ///
-               NOPAGEBREAK
+               NOPAGEBREAK,
+               ///
+               CONTEXTUAL
        };
        ///
        InsetNewpageParams() : kind(NEWPAGE) {}
@@ -55,6 +57,9 @@ public:
        static void string2params(std::string const &, InsetNewpageParams &);
        ///
        static std::string params2string(InsetNewpageParams const &);
+       /// Update the contextual information of this inset
+       void updateBuffer(ParIterator const &, UpdateType, bool const deleted = 
false) override;
+
 private:
        ///
        InsetCode lyxCode() const override { return NEWPAGE_CODE; }
@@ -92,6 +97,10 @@ private:
 
        ///
        InsetNewpageParams params_;
+       ///
+       std::string contextual_cmd_;
+       ///
+       std::string contextual_gui_;
 };
 
 } // namespace lyx
diff --git a/src/version.h b/src/version.h
index 0f833454ad..b71cf989f8 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 645 // spitz: math ref features
-#define LYX_FORMAT_TEX2LYX 645
+#define LYX_FORMAT_LYX 646 // spitz: InsetNewPage contextual
+#define LYX_FORMAT_TEX2LYX 646
 
 #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