cui/inc/treeopt.hrc                                        |    2 
 cui/source/options/treeopt.cxx                             |    2 
 cui/source/options/treeopthelper.cxx                       |    2 
 include/svx/optgrid.hxx                                    |    5 
 officecfg/registry/schema/org/openoffice/Office/Writer.xcs |   27 +-
 svx/source/dialog/optgrid.cxx                              |    8 
 svx/uiconfig/ui/optgridpage.ui                             |   68 ++++++
 sw/Library_sw.mk                                           |    1 
 sw/Library_swui.mk                                         |    1 
 sw/inc/cmdid.h                                             |    1 
 sw/inc/viewopt.hxx                                         |   12 +
 sw/source/core/inc/pagefrm.hxx                             |   12 +
 sw/source/core/layout/pagechg.cxx                          |  133 ++++++++++++-
 sw/source/core/layout/paintfrm.cxx                         |   90 ++++++++
 sw/source/core/text/porrst.cxx                             |   83 --------
 sw/source/ui/config/SwGridTabPage.cxx                      |   61 +++++
 sw/source/ui/dialog/swdlgfact.cxx                          |    4 
 sw/source/uibase/app/appopt.cxx                            |   20 +
 sw/source/uibase/config/SwBaselineGridConfig.cxx           |   83 ++++++++
 sw/source/uibase/config/usrpref.cxx                        |    3 
 sw/source/uibase/config/viewopt.cxx                        |    4 
 sw/source/uibase/inc/SwBaselineGridConfig.hxx              |   36 +++
 sw/source/uibase/inc/SwGridTabPage.hxx                     |   29 ++
 sw/source/uibase/inc/usrpref.hxx                           |    8 
 sw/source/uibase/uiview/pview.cxx                          |    1 
 25 files changed, 597 insertions(+), 99 deletions(-)

New commits:
commit 6f46f068d48310e43f09f3c5b0b73080995a2105
Author:     Tamás Zolnai <[email protected]>
AuthorDate: Mon Nov 24 14:16:25 2025 +0100
Commit:     Tamás Zolnai <[email protected]>
CommitDate: Mon Dec 15 10:12:40 2025 +0100

    tdf#169806: Display baseline grid for page line-spacing.
    
    1. Add a new option to the Grid tab page for displaying the baseline
    grid.
    * Add a new checkbox to LibreOffice Writer -> Grid tab page to
    enable/disable displaying of the grid.
    * Make the new option hidden by default and show it only for Writer
    normal view (see SwGridTabPage class).
    * Rename the tab page title from "Grid" to "Grids" to reflect the new
    content of the tab page (options for two different types of grids).
    
    2. Add a new configuration option for displaying the baseline grid.
    * Extend Writer configuration with a new section for baseline the grid
    option(s).
    * Introduce a new ConfigItem for the new baseline grid related option
    to allow saving it to and loading it from the user preferences. (see
    SwBaselineGridConfig class).
    * Handle the possible read-only state of the configuration option and
    lock the related checkbox on the grid tab page, if necessary.
    
    3. Compute the proper position of the baseline grid's horizontal lines.
    * First, extract the ComputeRegister() method to calculate the proper
    height/ascent values used for register-true rendering.
    * Use this ComputeRegister() method to calculate the proper
    height/ascent values both for the text formatting code and for the
    drawing code of the baseline grid.
    
    4. Draw the baseline grid.
    *  Draw the grid based on the reference style used by page
    line-spacing, if specified.
    * If there is no page line-spacing set, use the "standard" reference
    style (i.e. "Body text").
    * Draw the baseline grid on top of other objects (e.g. shapes,
    frames), so the user can verify the text alignment inside these objects
    as well.
    * Trigger a repaint of the whole page if the baseline grid is visible
    and page line-spacing settings are changed.
    
    5. Don't display the baseline grid when printing.
    * Don't display the grid for print preview, for printing,
    or for exporting to PDF.
    
    Change-Id: I40c4cd4beeab6b1416365e9e728bfe1a7756b5c5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195350
    Reviewed-by: Tamás Zolnai <[email protected]>
    Tested-by: Jenkins

diff --git a/cui/inc/treeopt.hrc b/cui/inc/treeopt.hrc
index 0edd9c3aa06d..48c7b06b89b6 100644
--- a/cui/inc/treeopt.hrc
+++ b/cui/inc/treeopt.hrc
@@ -71,7 +71,7 @@ const std::pair<TranslateId, sal_uInt16> 
SID_SW_EDITOPTIONS_RES[] =
     { NC_("SID_SW_EDITOPTIONS_RES", "General"),     RID_SW_TP_OPTLOAD_PAGE    
},
     { NC_("SID_SW_EDITOPTIONS_RES", "View"),       RID_SW_TP_CONTENT_OPT   },
     { NC_("SID_SW_EDITOPTIONS_RES", "Formatting Aids"),        
RID_SW_TP_OPTSHDWCRSR     },
-    { NC_("SID_SW_EDITOPTIONS_RES", "Grid"),        RID_SVXPAGE_GRID         },
+    { NC_("SID_SW_EDITOPTIONS_RES", "Grids"),        RID_SVXPAGE_GRID         
},
     { NC_("SID_SW_EDITOPTIONS_RES", "Basic Fonts 
(Western)"),RID_SW_TP_STD_FONT        },
     { NC_("SID_SW_EDITOPTIONS_RES", "Basic Fonts 
(Asian)"),RID_SW_TP_STD_FONT_CJK        },
     { NC_("SID_SW_EDITOPTIONS_RES", "Basic Fonts (CTL)"),      
RID_SW_TP_STD_FONT_CTL        },
diff --git a/cui/source/options/treeopt.cxx b/cui/source/options/treeopt.cxx
index 97e075332892..e77234275703 100644
--- a/cui/source/options/treeopt.cxx
+++ b/cui/source/options/treeopt.cxx
@@ -325,7 +325,7 @@ constexpr OptionsMapping_Impl OptionsMap_Impl[]
     { u"Writer"_ustr,             u"General"_ustr,              
RID_SW_TP_OPTLOAD_PAGE },
     { u"Writer"_ustr,             u"View"_ustr,                 
RID_SW_TP_CONTENT_OPT },
     { u"Writer"_ustr,             u"FormattingAids"_ustr,       
RID_SW_TP_OPTSHDWCRSR },
-    { u"Writer"_ustr,             u"Grid"_ustr,                 
RID_SVXPAGE_GRID },
+    { u"Writer"_ustr,             u"Grids"_ustr,                
RID_SVXPAGE_GRID },
     { u"Writer"_ustr,             u"BasicFontsWestern"_ustr,    
RID_SW_TP_STD_FONT },
     { u"Writer"_ustr,             u"BasicFontsAsian"_ustr,      
RID_SW_TP_STD_FONT_CJK },
     { u"Writer"_ustr,             u"BasicFontsCTL"_ustr,        
RID_SW_TP_STD_FONT_CTL },
diff --git a/cui/source/options/treeopthelper.cxx 
b/cui/source/options/treeopthelper.cxx
index 96510cc291b4..e7f9a173ae6d 100644
--- a/cui/source/options/treeopthelper.cxx
+++ b/cui/source/options/treeopthelper.cxx
@@ -80,7 +80,7 @@ static PageIdToFileNameMap_Impl FileMap_Impl[] = {
     { RID_SW_TP_OPTLOAD_PAGE, u""_ustr }, // General
     { RID_SW_TP_CONTENT_OPT, u""_ustr }, // View
     { RID_SW_TP_OPTSHDWCRSR, u""_ustr }, // FormattingAids
-    { RID_SVXPAGE_GRID, u""_ustr }, // Grid
+    { RID_SVXPAGE_GRID, u""_ustr }, // Grids
     { RID_SW_TP_STD_FONT, u""_ustr }, // BasicFontsWestern
     { RID_SW_TP_STD_FONT_CJK, u""_ustr }, // BasicFontsAsian
     { RID_SW_TP_STD_FONT_CTL, u""_ustr }, // BasicFontsCTL
diff --git a/include/svx/optgrid.hxx b/include/svx/optgrid.hxx
index d6dc7310def2..85c72b1c7d23 100644
--- a/include/svx/optgrid.hxx
+++ b/include/svx/optgrid.hxx
@@ -144,6 +144,11 @@ protected:
     std::unique_ptr<weld::MetricSpinButton> m_xMtrFldBezAngle;
     std::unique_ptr<weld::Widget> m_xMtrFldBezAngleImg;
 
+    // Writer-only baseline grid related items.
+    std::unique_ptr<weld::Widget> m_xBaselineGrid;
+    std::unique_ptr<weld::CheckButton> m_xCbxBaselineGridVisible;
+    std::unique_ptr<weld::Widget> m_xCbxBaselineGridVisibleImg;
+
     bool IsDrawMode() const { return m_Emode == DRAW_MODE; }
 
     DECL_LINK(ClickRotateHdl_Impl, weld::Toggleable&, void);
diff --git a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs 
b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
index 3ce84488d980..1d4b93cac434 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Writer.xcs
@@ -1505,7 +1505,7 @@
           <desc>Contains options for the grid.</desc>
         </info>
         <prop oor:name="SnapToGrid" oor:type="xs:boolean" oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document  Grid - [Section] 
Options -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Options -->
           <info>
             <desc>Moves frames, drawing elements, and form functions only 
between the grid points.</desc>
             <label>Snap to grid</label>
@@ -1513,7 +1513,7 @@
           <value>false</value>
         </prop>
         <prop oor:name="VisibleGrid" oor:type="xs:boolean" 
oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document  Grid - [Section] 
Options -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Options -->
           <info>
             <desc>Displays the grid.</desc>
             <label>Visible grid</label>
@@ -1521,7 +1521,7 @@
           <value>false</value>
         </prop>
         <prop oor:name="Synchronize" oor:type="xs:boolean" 
oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document  Grid - [Section] 
Options -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Options -->
           <info>
             <desc>Changes the current grid settings symmetrically. The 
resolution and subdivision for the X- and Y-axis remains the same.</desc>
             <label>Synchronize axes</label>
@@ -1534,7 +1534,7 @@
           <desc>Contains settings for specifying the grid resolution.</desc>
         </info>
         <prop oor:name="XAxis" oor:type="xs:int" oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document - Grid - [Section] 
Grid -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Grid -->
           <info>
             <desc>Defines the grid points distance in the X-axis [UNIT=1/100 
mm].</desc>
             <label>X Axis Resolution</label>
@@ -1542,7 +1542,7 @@
           <value>1000</value>
         </prop>
         <prop oor:name="YAxis" oor:type="xs:int" oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document - Grid - [Section] 
Grid -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Grid -->
           <info>
             <desc>Defines the grid points distance in the Y-axis [UNIT=1/100 
mm].</desc>
             <label>Y Axis Resolution</label>
@@ -1555,7 +1555,7 @@
           <desc>Contains settings for specifying the subdivision of the 
grid.</desc>
         </info>
         <prop oor:name="XAxis" oor:type="xs:int" oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document - Grid - [Section] 
Grid -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Grid -->
           <info>
             <desc>Specifies the number of intervals between two grid points on 
the X-axis.</desc>
             <label>X Axis Subdivision</label>
@@ -1563,7 +1563,7 @@
           <value>3</value>
         </prop>
         <prop oor:name="YAxis" oor:type="xs:int" oor:nillable="false">
-          <!-- UIHints: Tools - Options - Text document - Grid - [Section] 
Grid -->
+          <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - 
[Section] Grid -->
           <info>
             <desc>Defines the distance between the grid points on the 
Y-axis.</desc>
             <label>Y Axis Subdivision</label>
@@ -1572,6 +1572,19 @@
         </prop>
       </group>
     </group>
+    <group oor:name="BaselineGrid">
+      <info>
+        <desc>Contains various options for the baseline grid.</desc>
+      </info>
+      <prop oor:name="VisibleGrid" oor:type="xs:boolean" oor:nillable="false">
+        <!-- UIHints: Tools - Options - LibreOffice Writer - Grids - [Section] 
Baseline Grid -->
+        <info>
+          <desc>Displays the baseline grid for page line-spacing.</desc>
+          <label>Visible grid</label>
+        </info>
+        <value>false</value>
+      </prop>
+    </group>
     <group oor:name="DefaultFont">
       <info>
         <desc>Specifies the basic western fonts to be used.</desc>
diff --git a/svx/source/dialog/optgrid.cxx b/svx/source/dialog/optgrid.cxx
index 6447c47ae608..4bb23f2752ff 100644
--- a/svx/source/dialog/optgrid.cxx
+++ b/svx/source/dialog/optgrid.cxx
@@ -137,6 +137,9 @@ SvxGridTabPage::SvxGridTabPage(weld::Container* pPage, 
weld::DialogController* p
     , m_xMtrFldAngle(m_xBuilder->weld_metric_spin_button(u"mtrfldangle"_ustr, 
FieldUnit::DEGREE))
     , 
m_xMtrFldBezAngle(m_xBuilder->weld_metric_spin_button(u"mtrfldbezangle"_ustr, 
FieldUnit::DEGREE))
     , m_xMtrFldBezAngleImg(m_xBuilder->weld_widget(u"lockmtrfldbezangle"_ustr))
+    , m_xBaselineGrid(m_xBuilder->weld_widget(u"baselinegridframe"_ustr))
+    , 
m_xCbxBaselineGridVisible(m_xBuilder->weld_check_button(u"baselinegridvisible"_ustr))
+    , 
m_xCbxBaselineGridVisibleImg(m_xBuilder->weld_widget(u"lockbaselinegridvisible"_ustr))
 {
     // This page requires exchange Support
     SetExchangeSupport();
@@ -205,7 +208,7 @@ OUString SvxGridTabPage::GetAllStrings()
     OUStringBuffer sAllStrings;
     OUString labels[]
         = { u"label1"_ustr,    u"label2"_ustr, u"flddrawx"_ustr,  
u"flddrawy"_ustr, u"label6"_ustr, u"label7"_ustr, u"label3"_ustr,
-            u"divisionx"_ustr, u"label4"_ustr, u"divisiony"_ustr, 
u"label5"_ustr,   u"label8"_ustr, u"label9"_ustr };
+            u"divisionx"_ustr, u"label4"_ustr, u"divisiony"_ustr, 
u"label5"_ustr,   u"label8"_ustr, u"label9"_ustr, u"label10"_ustr };
 
     for (const auto& label : labels)
     {
@@ -215,7 +218,8 @@ OUString SvxGridTabPage::GetAllStrings()
 
     OUString checkButton[]
         = { u"usegridsnap"_ustr, u"gridvisible"_ustr, u"synchronize"_ustr, 
u"snaphelplines"_ustr, u"snapborder"_ustr,
-            u"snapframe"_ustr,   u"snappoints"_ustr,  u"ortho"_ustr,       
u"bigortho"_ustr,      u"rotate"_ustr };
+            u"snapframe"_ustr,   u"snappoints"_ustr,  u"ortho"_ustr,       
u"bigortho"_ustr,      u"rotate"_ustr,
+            u"baselinegridvisible"_ustr };
 
     for (const auto& check : checkButton)
     {
diff --git a/svx/uiconfig/ui/optgridpage.ui b/svx/uiconfig/ui/optgridpage.ui
index d8a2ae2f39a0..8f82305d05b4 100644
--- a/svx/uiconfig/ui/optgridpage.ui
+++ b/svx/uiconfig/ui/optgridpage.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2 -->
+<!-- Generated with glade 3.40.0 -->
 <interface domain="svx">
   <requires lib="gtk+" version="3.24"/>
   <object class="GtkAdjustment" id="adjustment1">
@@ -960,6 +960,72 @@
         <property name="position">2</property>
       </packing>
     </child>
+    <child>
+      <object class="GtkFrame" id="baselinegridframe">
+        <property name="no-show-all">True</property>
+        <property name="can-focus">False</property>
+        <property name="label-xalign">0</property>
+        <property name="shadow-type">none</property>
+        <child>
+          <!-- n-columns=2 n-rows=1 -->
+          <object class="GtkGrid" id="grid10">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="margin-start">12</property>
+            <property name="margin-top">6</property>
+            <property name="hexpand">True</property>
+            <property name="row-spacing">6</property>
+            <child>
+              <object class="GtkCheckButton" id="baselinegridvisible">
+                <property name="label" translatable="yes" 
context="optgridpage|baselinegridvisible">V_isible grid</property>
+                <property name="visible">True</property>
+                <property name="can-focus">True</property>
+                <property name="receives-default">False</property>
+                <property name="use-underline">True</property>
+                <property name="draw-indicator">True</property>
+                <child internal-child="accessible">
+                  <object class="AtkObject" id="baselinegridvisible-atkobject">
+                    <property name="AtkObject::accessible-description" 
translatable="yes" context="extended_tip|baselinegridvisible">Specifies whether 
to display the baseline grid for page line-spacing.</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="left-attach">1</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkImage" id="lockbaselinegridvisible">
+                <property name="can-focus">False</property>
+                <property name="no-show-all">True</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+                <property name="icon-name">res/lock.png</property>
+              </object>
+              <packing>
+                <property name="left-attach">0</property>
+                <property name="top-attach">0</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="label10">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="optgridpage|label10">Baseline Grid</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">False</property>
+        <property name="fill">True</property>
+        <property name="position">3</property>
+      </packing>
+    </child>
     <child internal-child="accessible">
       <object class="AtkObject" id="OptGridPage-atkobject">
         <property name="AtkObject::accessible-description" translatable="yes" 
context="extended_tip|OptGridPage">Specifies the settings for the configurable 
grid on your document pages. This grid helps you determine the exact position 
of your objects. You can also set this grid in line with the "magnetic" snap 
grid.</property>
diff --git a/sw/Library_sw.mk b/sw/Library_sw.mk
index f887b4fa24e9..7e4cd65039a0 100644
--- a/sw/Library_sw.mk
+++ b/sw/Library_sw.mk
@@ -633,6 +633,7 @@ $(eval $(call gb_Library_add_exception_objects,sw,\
     sw/source/uibase/config/fontcfg \
     sw/source/uibase/config/modcfg \
     sw/source/uibase/config/prtopt \
+    sw/source/uibase/config/SwBaselineGridConfig \
     sw/source/uibase/config/uinums \
     sw/source/uibase/config/usrpref \
     sw/source/uibase/config/viewopt \
diff --git a/sw/Library_swui.mk b/sw/Library_swui.mk
index cf025735337e..016519430421 100644
--- a/sw/Library_swui.mk
+++ b/sw/Library_swui.mk
@@ -95,6 +95,7 @@ $(eval $(call gb_Library_add_exception_objects,swui,\
     sw/source/ui/config/optcomp \
     sw/source/ui/config/optload \
     sw/source/ui/config/optpage \
+    sw/source/ui/config/SwGridTabPage \
     sw/source/ui/dialog/abstract \
     sw/source/ui/dialog/addrdlg \
     sw/source/ui/dialog/ascfldlg \
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index 4757f9f50174..5b1b63310c53 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -879,6 +879,7 @@ class SwUINumRuleItem;
 #define FN_TEXT_BOX                     (FN_PARAM2+28) /* TextBox Property*/
 #define FN_BOOKMARK_HIDDEN              (FN_PARAM2+29) /* Hidden Property of 
bookmarks*/
 #define FN_BOOKMARK_CONDITION           (FN_PARAM2+30) /* Condition Property 
of bookmarks*/
+#define FN_PARAM_BASELINE_GRID_VISIBLE  
TypedWhichId<SfxBoolItem>(FN_PARAM2+31) /* Baseline grid visibility */
 
 // Status: not more than 19!
 #define FN_STAT_PAGE                TypedWhichId<SfxStringListItem>(FN_STAT + 
1)
diff --git a/sw/inc/viewopt.hxx b/sw/inc/viewopt.hxx
index 64a80b5ffb64..a4120b6369fc 100644
--- a/sw/inc/viewopt.hxx
+++ b/sw/inc/viewopt.hxx
@@ -61,6 +61,7 @@ struct ViewOptFlags1
     bool bSnap : 1;
     bool bSynchronize : 1;
     bool bGridVisible : 1;
+    bool bBaselineGridVisible : 1;
     bool bOnlineSpell : 1;
     bool bTreatSubOutlineLevelsAsContent : 1;
     bool bShowInlineTooltips : 1; //tooltips on tracked changes
@@ -104,6 +105,7 @@ struct ViewOptFlags1
         , bSnap(false)
         , bSynchronize(false)
         , bGridVisible(false)
+        , bBaselineGridVisible(false)
         , bOnlineSpell(false)
         , bTreatSubOutlineLevelsAsContent(false)
         , bShowInlineTooltips(false)
@@ -146,6 +148,7 @@ struct ViewOptFlags1
             && bSnap == rOther.bSnap
             && bSynchronize == rOther.bSynchronize
             && bGridVisible == rOther.bGridVisible
+            && bBaselineGridVisible == rOther.bBaselineGridVisible
             && bOnlineSpell == rOther.bOnlineSpell
             && bTreatSubOutlineLevelsAsContent == 
rOther.bTreatSubOutlineLevelsAsContent
             && bShowInlineTooltips == rOther.bShowInlineTooltips
@@ -569,6 +572,15 @@ public:
     void SetGridVisible( bool b )
     { m_nCoreOptions.bGridVisible = b; }
 
+    bool IsBaselineGridVisible() const
+    {
+        return m_nCoreOptions.bBaselineGridVisible;
+    }
+    void SetBaselineGridVisible( bool bVisible )
+    {
+        m_nCoreOptions.bBaselineGridVisible = bVisible;
+    }
+
     bool IsOnlineSpell() const
     {
         return m_nCoreOptions.bOnlineSpell;
diff --git a/sw/source/core/inc/pagefrm.hxx b/sw/source/core/inc/pagefrm.hxx
index aa2af7e0ae4c..f5e2f503b16c 100644
--- a/sw/source/core/inc/pagefrm.hxx
+++ b/sw/source/core/inc/pagefrm.hxx
@@ -38,6 +38,7 @@ class SwAnchoredObject;
 namespace sw {
     class VirtPageNumHint;
 }
+class SwTextFormatColl;
 
 enum class SwPageFrameInvFlags : sal_uInt8
 {
@@ -173,6 +174,14 @@ public:
     // Sends a Prepare() to all ContentFrames caused by a changed register 
template
     void PrepareRegisterChg();
 
+    /** Computes height / ascent values used for register-true formatting.
+        @param[in]  pFormat     The paragraph format from which to derive the 
register-true parameters.
+        @param[out] rRegHeight  The computed text height for register-true 
formatting.
+        @param[out] rRegAscent  The computed text ascent for register-true 
formatting.
+    */
+    void ComputeRegister(const SwTextFormatColl* pFormat, sal_uInt16& 
rRegHeight,
+                         sal_uInt16& rRegAscent) const;
+
     // Appends a fly frame - the given one or a new one - at the page frame.
     // Needed for <Modify> and <MakeFrames>
     // - return value not needed any more
@@ -190,6 +199,9 @@ public:
     void PaintGrid( OutputDevice const * pOut, SwRect const &rRect ) const;
     bool HasGrid() const { return m_bHasGrid; }
 
+    /// Paints the baseline grid based on the reference style defined by the 
page line-spacing.
+    void PaintBaselineGrid( OutputDevice& rOututDevice ) const;
+
     void PaintDecorators( ) const;
     virtual void PaintSubsidiaryLines( const SwPageFrame*, const SwRect& ) 
const override;
     void AddSubsidiaryLinesBounds(const SwViewShell& rShell, RectangleVector& 
rRects) const;
diff --git a/sw/source/core/layout/pagechg.cxx 
b/sw/source/core/layout/pagechg.cxx
index abcfba0d4973..d62bb5b48d55 100644
--- a/sw/source/core/layout/pagechg.cxx
+++ b/sw/source/core/layout/pagechg.cxx
@@ -46,6 +46,7 @@
 #include <IDocumentDrawModelAccess.hxx>
 #include <IDocumentSettingAccess.hxx>
 #include <IDocumentFieldsAccess.hxx>
+#include <IDocumentDeviceAccess.hxx>
 #include <dcontact.hxx>
 #include <hints.hxx>
 #include <FrameControlsManager.hxx>
@@ -66,6 +67,8 @@
 #include <calbck.hxx>
 #include <txtfly.hxx>
 #include <frmatr.hxx>
+#include <swfntcch.hxx>
+#include <vcl/svapp.hxx>
 
 using namespace ::com::sun::star;
 
@@ -1054,21 +1057,135 @@ void SwPageFrame::PrepareRegisterChg()
         if( !IsAnLower( pFrame ) )
             break;
     }
-    if( !GetSortedObjs() )
+
+    if( GetSortedObjs() )
+    {
+        for(SwAnchoredObject* pAnchoredObj : *GetSortedObjs())
+        {
+            // #i28701#
+            if ( auto pFly = pAnchoredObj->DynCastFlyFrame() )
+            {
+                pFrame = pFly->ContainsContent();
+                while ( pFrame )
+                {
+                    ::lcl_PrepFlyInCntRegister( pFrame );
+                    pFrame = pFrame->GetNextContentFrame();
+                }
+            }
+        }
+    }
+
+    // If the baseline grid is visible, a repaint of the page must be 
triggered.
+    const SwRootFrame* pRootFrame = getRootFrame();
+    if (!pRootFrame)
+    {
         return;
+    }
 
-    for(SwAnchoredObject* pAnchoredObj : *GetSortedObjs())
+    const SwViewShell* pViewShell = pRootFrame->GetCurrShell();
+    if (!pViewShell)
     {
-        // #i28701#
-        if ( auto pFly = pAnchoredObj->DynCastFlyFrame() )
+        return;
+    }
+
+    const SwViewOption* pViewOption = pViewShell->GetViewOptions();
+    if (!pViewOption)
+    {
+        return;
+    }
+
+    if (pViewOption->IsBaselineGridVisible())
+    {
+        InvalidatePage(this);
+        SetCompletePaint();
+    }
+}
+
+void SwPageFrame::ComputeRegister(const SwTextFormatColl* pFormat, sal_uInt16& 
rRegHeight,
+                                  sal_uInt16& rRegAscent) const
+{
+    rRegHeight = 0;
+    rRegAscent = 0;
+
+    if (!pFormat)
+    {
+        return;
+    }
+
+    const SvxLineSpacingItem &rSpace = pFormat->GetLineSpacing();
+    if( SvxLineSpaceRule::Fix == rSpace.GetLineSpaceRule() )
+    {
+        rRegHeight = rSpace.GetLineHeight();
+        rRegAscent = ( 4 * rRegHeight ) / 5;
+    }
+    else
+    {
+        SwViewShell *pSh = getRootFrame()->GetCurrShell();
+        SwFontAccess aFontAccess( pFormat, pSh );
+        SwFont aFnt( aFontAccess.Get()->GetFont() );
+
+        OutputDevice *pOut = nullptr;
+        if(pSh)
+        {
+            if( !pSh->GetViewOptions()->getBrowseMode() ||
+                pSh->GetViewOptions()->IsPrtFormat() )
+                pOut = 
pSh->GetDoc()->getIDocumentDeviceAccess().getReferenceDevice( true );
+
+            if(!pOut )
+                pOut = pSh->GetWin()->GetOutDev();
+        }
+        else
         {
-            pFrame = pFly->ContainsContent();
-            while ( pFrame )
+            pOut = Application::GetDefaultDevice();
+        }
+
+        MapMode aOldMap( pOut->GetMapMode() );
+        pOut->SetMapMode( MapMode( MapUnit::MapTwip ) );
+
+        aFnt.ChgFnt( pSh, *pOut );
+        rRegHeight = aFnt.GetHeight( pSh, *pOut );
+        sal_uInt16 nNetHeight = rRegHeight;
+
+        switch( rSpace.GetLineSpaceRule() )
+        {
+            case SvxLineSpaceRule::Auto:
+            break;
+            case SvxLineSpaceRule::Min:
+            {
+                if( rRegHeight < rSpace.GetLineHeight() )
+                    rRegHeight = rSpace.GetLineHeight();
+                break;
+            }
+            default:
+                OSL_FAIL( ": unknown LineSpaceRule" );
+        }
+        switch( rSpace.GetInterLineSpaceRule() )
+        {
+            case SvxInterLineSpaceRule::Off:
+            break;
+            case SvxInterLineSpaceRule::Prop:
+            {
+                tools::Long nTmp = rSpace.GetPropLineSpace();
+                if( nTmp < 50 )
+                    nTmp = nTmp ? 50 : 100;
+                nTmp *= rRegHeight;
+                nTmp /= 100;
+                if( !nTmp )
+                    ++nTmp;
+                rRegHeight = o3tl::narrowing<sal_uInt16>(nTmp);
+                nNetHeight = rRegHeight;
+                break;
+            }
+            case SvxInterLineSpaceRule::Fix:
             {
-                ::lcl_PrepFlyInCntRegister( pFrame );
-                pFrame = pFrame->GetNextContentFrame();
+                rRegHeight = rRegHeight + rSpace.GetInterLineSpace();
+                nNetHeight = rRegHeight;
+                break;
             }
+            default: OSL_FAIL( ": unknown InterLineSpaceRule" );
         }
+        rRegAscent = rRegHeight - nNetHeight + aFnt.GetAscent( pSh, *pOut );
+        pOut->SetMapMode( aOldMap );
     }
 }
 
diff --git a/sw/source/core/layout/paintfrm.cxx 
b/sw/source/core/layout/paintfrm.cxx
index cddf1e100fbf..ae9a794fec55 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -81,6 +81,7 @@
 #include <DocumentSettingManager.hxx>
 #include <IDocumentDeviceAccess.hxx>
 #include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentStylePoolAccess.hxx>
 
 #include <ndole.hxx>
 #include <PostItMgr.hxx>
@@ -129,6 +130,7 @@
 #include <ndtxt.hxx>
 #include <unotools/configmgr.hxx>
 #include <vcl/hatch.hxx>
+#include <poolfmt.hxx>
 
 using namespace ::editeng;
 using namespace ::com::sun::star;
@@ -3487,6 +3489,8 @@ void SwRootFrame::PaintSwFrame(vcl::RenderContext& 
rRenderContext, SwRect const&
                     pPageView->DrawPageViewGrid(*pSh->GetOut(), 
aPaintRect.SVRect(), pSh->GetViewOptions()->GetTextGridColor() );
                 }
 
+                pPage->PaintBaselineGrid( *pSh->GetOut() );
+
                 // #i68597#
                 // moved paint post-process for DrawingLayer overlay here, see 
above
                 {
@@ -6185,6 +6189,92 @@ void SwPageFrame::PaintGrid( OutputDevice const * pOut, 
SwRect const &rRect ) co
     }
 }
 
+void SwPageFrame::PaintBaselineGrid(OutputDevice& rOututDevice) const
+{
+    // Not displayed when printing.
+    if (rOututDevice.GetOutDevType() == OUTDEV_PRINTER)
+    {
+        return;
+    }
+
+    const SwRootFrame* pRootFrame = getRootFrame();
+    if (!pRootFrame)
+    {
+        return;
+    }
+
+    const SwViewShell* pViewShell = pRootFrame->GetCurrShell();
+    if (!pViewShell)
+    {
+        return;
+    }
+
+    const SwViewOption* pViewOption = pViewShell->GetViewOptions();
+    if (!pViewOption)
+    {
+        return;
+    }
+
+    // Draw only if the baseline grid is set to be visible.
+    if (!pViewOption->IsBaselineGridVisible())
+    {
+        return;
+    }
+
+    const SwPageDesc* pPageDesc = GetPageDesc();
+    if (!pPageDesc)
+    {
+        return;
+    }
+
+    sal_uInt16 nLineHeight = 0;
+    sal_uInt16 nLineOffset = 0;
+    // If page line-spacing is enabled, use the selected paragraph style to 
compute height/ascent values.
+    const SwTextFormatColl* pRegisterFormat = 
pPageDesc->GetRegisterFormatColl();
+    if (pRegisterFormat)
+    {
+        ComputeRegister(pRegisterFormat, nLineHeight, nLineOffset);
+    }
+    else
+    {
+        // If page line spacing is disabled, use the standard paragraph style 
("Body text")
+        // to compute height/ascent values.
+        SwDoc* pDoc = pViewShell->GetDoc();
+        if (!pDoc)
+        {
+            return;
+        }
+        const SwTextFormatColl* pDefaultFormat
+            = 
pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_TEXT);
+        if (!pDefaultFormat)
+        {
+            return;
+        }
+        ComputeRegister(pDefaultFormat, nLineHeight, nLineOffset);
+    }
+
+    const SwLayoutFrame* pBody = FindBodyCont();
+    if (!pBody)
+    {
+        return;
+    }
+
+    SwRect aGridArea(pBody->getFramePrintArea());
+    aGridArea += pBody->getFrameArea().Pos();
+    // Grid area starts at the first baseline position of the page.
+    aGridArea.AddTop(nLineOffset);
+
+    const Color aGridColor(COL_BLACK);
+    const Color aOriginalLineColor(rOututDevice.GetLineColor());
+    rOututDevice.SetLineColor(aGridColor);
+
+    const tools::Long nLineWidth = aGridArea.Right() - aGridArea.Left();
+    rOututDevice.DrawGrid(aGridArea.SVRect(), Size(nLineWidth, nLineHeight),
+                          DrawGridFlags::HorzLines);
+
+    rOututDevice.SetLineColor(aOriginalLineColor);
+}
+
 /**
  * Paint margin area of a page
  *
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index a17d345eaf09..e367960177ed 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -554,7 +554,8 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, 
sal_uInt16& rRegDiff )
         pFrame = pFrame->FindPageFrame();
         if( pFrame->IsPageFrame() )
         {
-            SwPageDesc* pDesc = const_cast<SwPageFrame*>(static_cast<const 
SwPageFrame*>(pFrame))->FindPageDesc();
+            const SwPageFrame* pPage = static_cast<const SwPageFrame*>(pFrame);
+            SwPageDesc* pDesc = 
const_cast<SwPageFrame*>(pPage)->FindPageDesc();
             if( pDesc )
             {
                 rRegDiff = pDesc->GetRegHeight();
@@ -563,80 +564,12 @@ bool SwTextFrame::FillRegister( SwTwips& rRegStart, 
sal_uInt16& rRegDiff )
                     const SwTextFormatColl *pFormat = 
pDesc->GetRegisterFormatColl();
                     if( pFormat )
                     {
-                        const SvxLineSpacingItem &rSpace = 
pFormat->GetLineSpacing();
-                        if( SvxLineSpaceRule::Fix == rSpace.GetLineSpaceRule() 
)
-                        {
-                            rRegDiff = rSpace.GetLineHeight();
-                            pDesc->SetRegHeight( rRegDiff );
-                            pDesc->SetRegAscent( ( 4 * rRegDiff ) / 5 );
-                        }
-                        else
-                        {
-                            SwViewShell *pSh = getRootFrame()->GetCurrShell();
-                            SwFontAccess aFontAccess( pFormat, pSh );
-                            SwFont aFnt( aFontAccess.Get()->GetFont() );
-
-                            OutputDevice *pOut = nullptr;
-                            if( !pSh || 
!pSh->GetViewOptions()->getBrowseMode() ||
-                                pSh->GetViewOptions()->IsPrtFormat() )
-                                pOut = 
GetDoc().getIDocumentDeviceAccess().getReferenceDevice( true );
-
-                            if( pSh && !pOut )
-                                pOut = pSh->GetWin()->GetOutDev();
-
-                            if( !pOut )
-                                pOut = Application::GetDefaultDevice();
-
-                            MapMode aOldMap( pOut->GetMapMode() );
-                            pOut->SetMapMode( MapMode( MapUnit::MapTwip ) );
-
-                            aFnt.ChgFnt( pSh, *pOut );
-                            rRegDiff = aFnt.GetHeight( pSh, *pOut );
-                            sal_uInt16 nNetHeight = rRegDiff;
-
-                            switch( rSpace.GetLineSpaceRule() )
-                            {
-                                case SvxLineSpaceRule::Auto:
-                                break;
-                                case SvxLineSpaceRule::Min:
-                                {
-                                    if( rRegDiff < rSpace.GetLineHeight() )
-                                        rRegDiff = rSpace.GetLineHeight();
-                                    break;
-                                }
-                                default:
-                                    OSL_FAIL( ": unknown LineSpaceRule" );
-                            }
-                            switch( rSpace.GetInterLineSpaceRule() )
-                            {
-                                case SvxInterLineSpaceRule::Off:
-                                break;
-                                case SvxInterLineSpaceRule::Prop:
-                                {
-                                    tools::Long nTmp = 
rSpace.GetPropLineSpace();
-                                    if( nTmp < 50 )
-                                        nTmp = nTmp ? 50 : 100;
-                                    nTmp *= rRegDiff;
-                                    nTmp /= 100;
-                                    if( !nTmp )
-                                        ++nTmp;
-                                    rRegDiff = 
o3tl::narrowing<sal_uInt16>(nTmp);
-                                    nNetHeight = rRegDiff;
-                                    break;
-                                }
-                                case SvxInterLineSpaceRule::Fix:
-                                {
-                                    rRegDiff = rRegDiff + 
rSpace.GetInterLineSpace();
-                                    nNetHeight = rRegDiff;
-                                    break;
-                                }
-                                default: OSL_FAIL( ": unknown 
InterLineSpaceRule" );
-                            }
-                            pDesc->SetRegHeight( rRegDiff );
-                            pDesc->SetRegAscent( rRegDiff - nNetHeight +
-                                                 aFnt.GetAscent( pSh, *pOut ) 
);
-                            pOut->SetMapMode( aOldMap );
-                        }
+                        sal_uInt16 nRegHeight = 0;
+                        sal_uInt16 nRegAscent = 0;
+                        pPage->ComputeRegister(pFormat, nRegHeight, 
nRegAscent);
+                        pDesc->SetRegHeight( nRegHeight );
+                        pDesc->SetRegAscent( nRegAscent );
+                        rRegDiff = pDesc->GetRegHeight();
                     }
                 }
                 const tools::Long nTmpDiff = pDesc->GetRegAscent() - rRegDiff;
diff --git a/sw/source/ui/config/SwGridTabPage.cxx 
b/sw/source/ui/config/SwGridTabPage.cxx
new file mode 100644
index 000000000000..fa1d557de82c
--- /dev/null
+++ b/sw/source/ui/config/SwGridTabPage.cxx
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <cmdid.h>
+#include <SwGridTabPage.hxx>
+
+#include <officecfg/Office/Writer.hxx>
+#include <svl/eitem.hxx>
+
+SwGridTabPage::SwGridTabPage(weld::Container* pPage, weld::DialogController* 
pController,
+                             const SfxItemSet& rItemSet)
+    : SvxGridTabPage(pPage, pController, rItemSet)
+{
+    m_xBaselineGrid->show();
+}
+
+bool SwGridTabPage::FillItemSet(SfxItemSet* pItemSet)
+{
+    bool bModified = SvxGridTabPage::FillItemSet(pItemSet);
+
+    if (m_xCbxBaselineGridVisible->get_state_changed_from_saved())
+    {
+        pItemSet->Put(
+            SfxBoolItem(FN_PARAM_BASELINE_GRID_VISIBLE, 
m_xCbxBaselineGridVisible->get_active()));
+        bModified = true;
+    }
+
+    return bModified;
+}
+
+void SwGridTabPage::Reset(const SfxItemSet* pItemSet)
+{
+    SvxGridTabPage::Reset(pItemSet);
+
+    if (const SfxBoolItem* pItem = 
pItemSet->GetItemIfSet(FN_PARAM_BASELINE_GRID_VISIBLE, false))
+    {
+        m_xCbxBaselineGridVisible->set_active(pItem->GetValue());
+    }
+
+    const bool bReadOnly = 
officecfg::Office::Writer::BaselineGrid::VisibleGrid::isReadOnly();
+    m_xCbxBaselineGridVisible->set_sensitive(!bReadOnly);
+    m_xCbxBaselineGridVisibleImg->set_visible(bReadOnly);
+    m_xCbxBaselineGridVisible->save_state();
+}
+
+std::unique_ptr<SfxTabPage> SwGridTabPage::Create(weld::Container* pPage,
+                                                  weld::DialogController* 
pController,
+                                                  const SfxItemSet* pItemSet)
+{
+    return std::make_unique<SwGridTabPage>(pPage, pController, *pItemSet);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/ui/dialog/swdlgfact.cxx 
b/sw/source/ui/dialog/swdlgfact.cxx
index a29d8e86a175..c1fec98137b7 100644
--- a/sw/source/ui/dialog/swdlgfact.cxx
+++ b/sw/source/ui/dialog/swdlgfact.cxx
@@ -94,6 +94,7 @@
 #include <formatlinebreak.hxx>
 #include <translatelangselect.hxx>
 #include <copyfielddlg.hxx>
+#include <SwGridTabPage.hxx>
 
 using namespace css::frame;
 using namespace css::uno;
@@ -1290,6 +1291,9 @@ CreateTabPage 
SwAbstractDialogFactory_Impl::GetTabPageCreatorFunc( sal_uInt16 nI
         case RID_SW_TP_COMPARISON_OPT :
             pRet = SwCompareOptionsTabPage::Create;
         break;
+        case RID_SVXPAGE_GRID :
+            pRet = SwGridTabPage::Create;
+        break;
     }
 
     return pRet;
diff --git a/sw/source/uibase/app/appopt.cxx b/sw/source/uibase/app/appopt.cxx
index bcd5c69d725a..927eeae82842 100644
--- a/sw/source/uibase/app/appopt.cxx
+++ b/sw/source/uibase/app/appopt.cxx
@@ -103,7 +103,8 @@ std::optional<SfxItemSet> SwModule::CreateItemSet( 
sal_uInt16 nId )
             FN_PARAM_WRTSHELL, FN_PARAM_WRTSHELL,
             FN_PARAM_SHADOWCURSOR, FN_PARAM_SHADOWCURSOR,
             FN_PARAM_CRSR_IN_PROTECTED, FN_PARAM_CRSR_IN_PROTECTED,
-            FN_PARAM_FMT_AIDS_AUTOCOMPL, FN_PARAM_FMT_AIDS_AUTOCOMPL>
+            FN_PARAM_FMT_AIDS_AUTOCOMPL, FN_PARAM_FMT_AIDS_AUTOCOMPL,
+            FN_PARAM_BASELINE_GRID_VISIBLE, FN_PARAM_BASELINE_GRID_VISIBLE>
         aRet(GetPool());
 
     aRet.Put( SwDocDisplayItem( aViewOpt ) );
@@ -202,6 +203,9 @@ std::optional<SfxItemSet> SwModule::CreateItemSet( 
sal_uInt16 nId )
 
     aRet.Put(aGridItem);
 
+    // Baseline grid options
+    aRet.Put( SfxBoolItem(FN_PARAM_BASELINE_GRID_VISIBLE, 
aViewOpt.IsBaselineGridVisible()));
+
     // Options for PrintTabPage
     const SwPrintData* pOpt = GetPrtOptions(!bTextDialog);
     SwAddPrinterItem aAddPrinterItem(*pOpt );
@@ -372,6 +376,12 @@ void SwModule::ApplyItemSet( sal_uInt16 nId, const 
SfxItemSet& rSet )
         }
     }
 
+    // Baseline grid options
+    if( const SfxBoolItem* pItem = rSet.GetItemIfSet( 
FN_PARAM_BASELINE_GRID_VISIBLE, false ))
+    {
+        aViewOpt.SetBaselineGridVisible(pItem->GetValue());
+    }
+
     // Interpret Writer Printer Options
     if( const SwAddPrinterItem* pAddPrinterAttr = rSet.GetItemIfSet( 
FN_PARAM_ADDPRINTER, false ) )
     {
@@ -454,9 +464,15 @@ std::unique_ptr<SfxTabPage> SwModule::CreateTabPage( 
sal_uInt16 nId, weld::Conta
             break;
         }
         case RID_SW_TP_HTML_OPTGRID_PAGE:
-        case RID_SVXPAGE_GRID:
             xRet = SvxGridTabPage::Create(pPage, pController, rSet);
         break;
+        case RID_SVXPAGE_GRID:
+        {
+            SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
+            ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId );
+            xRet = (*fnCreatePage)( pPage, pController, &rSet );
+            break;
+        }
 
         case RID_SW_TP_STD_FONT:
         case RID_SW_TP_STD_FONT_CJK:
diff --git a/sw/source/uibase/config/SwBaselineGridConfig.cxx 
b/sw/source/uibase/config/SwBaselineGridConfig.cxx
new file mode 100644
index 000000000000..11457ace3a5b
--- /dev/null
+++ b/sw/source/uibase/config/SwBaselineGridConfig.cxx
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <ranges>
+
+#include <SwBaselineGridConfig.hxx>
+#include <usrpref.hxx>
+
+#include <o3tl/any.hxx>
+#include <osl/diagnose.h>
+
+SwBaselineGridConfig::SwBaselineGridConfig(SwMasterUsrPref& rParent)
+    : ConfigItem(u"Office.Writer/BaselineGrid"_ustr)
+    , m_rParent(rParent)
+{
+    Load();
+    EnableNotification(GetPropertyNames());
+}
+
+css::uno::Sequence<OUString> SwBaselineGridConfig::GetPropertyNames()
+{
+    static css::uno::Sequence<OUString> aNames{
+        u"VisibleGrid"_ustr, // 0
+    };
+    return aNames;
+}
+
+void SwBaselineGridConfig::ImplCommit()
+{
+    const css::uno::Sequence<OUString> aNames = GetPropertyNames();
+    css::uno::Sequence<css::uno::Any> aValues(aNames.getLength());
+    css::uno::Any* pValues = aValues.getArray();
+
+    for (sal_Int32 nProp : std::views::iota(0, aNames.getLength()))
+    {
+        switch (nProp)
+        {
+            case 0: // "VisibleGrid"
+                pValues[nProp] <<= m_rParent.IsBaselineGridVisible();
+                break;
+        }
+    }
+    PutProperties(aNames, aValues);
+}
+
+void SwBaselineGridConfig::Load()
+{
+    const css::uno::Sequence<OUString> aNames = GetPropertyNames();
+    const css::uno::Sequence<css::uno::Any> aValues = GetProperties(aNames);
+
+    OSL_ENSURE(aValues.getLength() == aNames.getLength(), "GetProperties 
failed");
+    if (aValues.getLength() != aNames.getLength())
+        return;
+
+    const css::uno::Any* pValues = aValues.getConstArray();
+    for (sal_Int32 nProp : std::views::iota(0, aNames.getLength()))
+    {
+        if (pValues[nProp].hasValue())
+        {
+            switch (nProp)
+            {
+                case 0: // "VisibleGrid"
+                {
+                    const bool bVisible = 
*o3tl::doAccess<bool>(pValues[nProp]);
+                    m_rParent.SetBaselineGridVisible(bVisible);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void SwBaselineGridConfig::Notify(const css::uno::Sequence<OUString>&) { 
Load(); }
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/uibase/config/usrpref.cxx 
b/sw/source/uibase/config/usrpref.cxx
index 1308ba687625..f96b66cc27a0 100644
--- a/sw/source/uibase/config/usrpref.cxx
+++ b/sw/source/uibase/config/usrpref.cxx
@@ -71,7 +71,8 @@ SwMasterUsrPref::SwMasterUsrPref(bool bWeb) :
     m_aGridConfig(bWeb, *this),
     m_aCursorConfig(*this),
     m_pWebColorConfig(bWeb ? new SwWebColorConfig(*this) : nullptr),
-    m_aFmtAidsAutoComplConfig(*this)
+    m_aFmtAidsAutoComplConfig(*this),
+    m_aBaselineGridConfig(bWeb ? std::nullopt : 
std::make_optional<SwBaselineGridConfig>(*this))
 {
     if (comphelper::IsFuzzing())
     {
diff --git a/sw/source/uibase/config/viewopt.cxx 
b/sw/source/uibase/config/viewopt.cxx
index 0fc106ee026c..6c106d8e35b6 100644
--- a/sw/source/uibase/config/viewopt.cxx
+++ b/sw/source/uibase/config/viewopt.cxx
@@ -727,6 +727,10 @@ void ViewOptFlags1::dumpAsXml(xmlTextWriterPtr pWriter) 
const
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
                                 
BAD_CAST(OString::boolean(bGridVisible).getStr()));
     (void)xmlTextWriterEndElement(pWriter);
+    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("bBaselineGridVisible"));
+    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
+                                
BAD_CAST(OString::boolean(bBaselineGridVisible).getStr()));
+    (void)xmlTextWriterEndElement(pWriter);
     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("bOnlineSpell"));
     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
                                 
BAD_CAST(OString::boolean(bOnlineSpell).getStr()));
diff --git a/sw/source/uibase/inc/SwBaselineGridConfig.hxx 
b/sw/source/uibase/inc/SwBaselineGridConfig.hxx
new file mode 100644
index 000000000000..54cc80de15c6
--- /dev/null
+++ b/sw/source/uibase/inc/SwBaselineGridConfig.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <unotools/configitem.hxx>
+
+#include <com/sun/star/uno/Sequence.h>
+
+class SwMasterUsrPref;
+
+/// Configuration item that manages baseline grid related options (e.g. 
visibility of the grid).
+class SwBaselineGridConfig final : public utl::ConfigItem
+{
+private:
+    SwMasterUsrPref& m_rParent;
+
+    static css::uno::Sequence<OUString> GetPropertyNames();
+
+    virtual void ImplCommit() override;
+
+public:
+    SwBaselineGridConfig(SwMasterUsrPref& rParent);
+
+    virtual void Notify(const css::uno::Sequence<OUString>& rPropertyNames) 
override;
+    void Load();
+    using ConfigItem::SetModified;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/SwGridTabPage.hxx 
b/sw/source/uibase/inc/SwGridTabPage.hxx
new file mode 100644
index 000000000000..313d211ff1c5
--- /dev/null
+++ b/sw/source/uibase/inc/SwGridTabPage.hxx
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/optgrid.hxx>
+
+/// Grid tab page class that handles Writer-only grid settings (e.g. baseline 
grid options).
+class SwGridTabPage final : public SvxGridTabPage
+{
+public:
+    SwGridTabPage(weld::Container* pPage, weld::DialogController* pController,
+                  const SfxItemSet& rItemSet);
+
+    static std::unique_ptr<SfxTabPage>
+    Create(weld::Container* pPage, weld::DialogController* pController, const 
SfxItemSet* pItemSet);
+
+    virtual bool FillItemSet(SfxItemSet* pItemSet) override;
+    virtual void Reset(const SfxItemSet* pItemSet) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/sw/source/uibase/inc/usrpref.hxx b/sw/source/uibase/inc/usrpref.hxx
index 74789e15f641..151fe774d108 100644
--- a/sw/source/uibase/inc/usrpref.hxx
+++ b/sw/source/uibase/inc/usrpref.hxx
@@ -24,6 +24,8 @@
 #include <fldupde.hxx>
 #include <viewopt.hxx>
 #include <tools/fldunit.hxx>
+#include <optional>
+#include "SwBaselineGridConfig.hxx"
 
 class SwMasterUsrPref;
 
@@ -176,6 +178,7 @@ class SwMasterUsrPref : public SwViewOption
     SwCursorConfig      m_aCursorConfig;
     std::unique_ptr<SwWebColorConfig>   m_pWebColorConfig;
     SwFmtAidsAutoComplConfig m_aFmtAidsAutoComplConfig;
+    std::optional<SwBaselineGridConfig> m_aBaselineGridConfig; // Not 
available in web view
 
 public:
     SwMasterUsrPref(bool bWeb);
@@ -192,6 +195,11 @@ public:
             if(m_pWebColorConfig)
                 m_pWebColorConfig->SetModified();
             m_aFmtAidsAutoComplConfig.SetModified();
+
+            if(m_aBaselineGridConfig.has_value())
+            {
+                m_aBaselineGridConfig->SetModified();
+            }
         }
 
     void SetUpdateLinkMode(sal_Int32 nSet, bool bNoModify = false)
diff --git a/sw/source/uibase/uiview/pview.cxx 
b/sw/source/uibase/uiview/pview.cxx
index 24a868369a17..87b07864ba44 100644
--- a/sw/source/uibase/uiview/pview.cxx
+++ b/sw/source/uibase/uiview/pview.cxx
@@ -1129,6 +1129,7 @@ void SwPagePreview::Init()
     aOpt.SetTable( true );
     aOpt.SetSnap( false );
     aOpt.SetGridVisible( false );
+    aOpt.SetBaselineGridVisible( false );
     aOpt.SetOnlineSpell( false );
     aOpt.SetHideWhitespaceMode( false );
 

Reply via email to